1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* 2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright 2008, The Android Open Source Project 3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 466ce3e08c5632a20ea66bde6dd76397041edf034Mark Salyzyn * Licensed under the Apache License, Version 2.0 (the "License"); 566ce3e08c5632a20ea66bde6dd76397041edf034Mark Salyzyn * you may not use this file except in compliance with the License. 666ce3e08c5632a20ea66bde6dd76397041edf034Mark Salyzyn * You may obtain a copy of the License at 7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 866ce3e08c5632a20ea66bde6dd76397041edf034Mark Salyzyn * http://www.apache.org/licenses/LICENSE-2.0 9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * 1066ce3e08c5632a20ea66bde6dd76397041edf034Mark Salyzyn * Unless required by applicable law or agreed to in writing, software 1166ce3e08c5632a20ea66bde6dd76397041edf034Mark Salyzyn * distributed under the License is distributed on an "AS IS" BASIS, 1266ce3e08c5632a20ea66bde6dd76397041edf034Mark Salyzyn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1366ce3e08c5632a20ea66bde6dd76397041edf034Mark Salyzyn * 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 <arpa/inet.h> 1866ce3e08c5632a20ea66bde6dd76397041edf034Mark Salyzyn#include <errno.h> 19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/if.h> 20c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak#include <linux/if_ether.h> 21c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak#include <linux/if_arp.h> 2247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti#include <linux/netlink.h> 23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <linux/route.h> 248984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik#include <linux/ipv6_route.h> 2547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti#include <linux/rtnetlink.h> 2647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti#include <linux/sockios.h> 2766ce3e08c5632a20ea66bde6dd76397041edf034Mark Salyzyn#include <net/if.h> 2866ce3e08c5632a20ea66bde6dd76397041edf034Mark Salyzyn#include <netdb.h> 2966ce3e08c5632a20ea66bde6dd76397041edf034Mark Salyzyn#include <netinet/in.h> 3066ce3e08c5632a20ea66bde6dd76397041edf034Mark Salyzyn#include <pthread.h> 3166ce3e08c5632a20ea66bde6dd76397041edf034Mark Salyzyn#include <stdio.h> 3266ce3e08c5632a20ea66bde6dd76397041edf034Mark Salyzyn#include <stdlib.h> 3366ce3e08c5632a20ea66bde6dd76397041edf034Mark Salyzyn#include <string.h> 3466ce3e08c5632a20ea66bde6dd76397041edf034Mark Salyzyn#include <sys/select.h> 3566ce3e08c5632a20ea66bde6dd76397041edf034Mark Salyzyn#include <sys/socket.h> 3666ce3e08c5632a20ea66bde6dd76397041edf034Mark Salyzyn#include <sys/types.h> 3766ce3e08c5632a20ea66bde6dd76397041edf034Mark Salyzyn#include <unistd.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/properties.h> 4230f991f251940be3ed11566fb71139852286f68aMark Salyzyn#include <log/log.h> 43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else 448d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block#define ALOGD printf 45ae8b56c0d17a97aff0b98e6405c7cc9811bbbc3dSteve Block#define ALOGW printf 46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 4866ce3e08c5632a20ea66bde6dd76397041edf034Mark Salyzyn#include "netutils/ifc.h" 4966ce3e08c5632a20ea66bde6dd76397041edf034Mark Salyzyn 509b828adfad09200f3f1bd3602187fe3dd5335774Elliott Hughes#if defined(__ANDROID__) 512d640c2640b957f704d86fcaea6e5a4af54dde2cElliott Hughes/* SIOCKILLADDR is an Android extension. */ 522d640c2640b957f704d86fcaea6e5a4af54dde2cElliott Hughes#define SIOCKILLADDR 0x8939 532d640c2640b957f704d86fcaea6e5a4af54dde2cElliott Hughes#endif 542d640c2640b957f704d86fcaea6e5a4af54dde2cElliott Hughes 55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int ifc_ctl_sock = -1; 568984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naikstatic int ifc_ctl_sock6 = -1; 57cebcd450c6ca3de5106ef3d817d5b760f5d57fbeDmitry Shmidtstatic pthread_mutex_t ifc_sock_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; 58cebcd450c6ca3de5106ef3d817d5b760f5d57fbeDmitry Shmidtstatic pthread_mutex_t ifc_sock6_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; 59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid printerr(char *fmt, ...); 60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 61b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt#define DBG 0 6247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti#define INET_ADDRLEN 4 6347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti#define INET6_ADDRLEN 16 64b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt 6509dd819d2794caf1a17cd03592c100755fb25577Robert Greenwaltin_addr_t prefixLengthToIpv4Netmask(int prefix_length) 6609dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt{ 6709dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt in_addr_t mask = 0; 6809dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt 6909dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt // C99 (6.5.7): shifts of 32 bits have undefined results 7009dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt if (prefix_length <= 0 || prefix_length > 32) { 7109dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt return 0; 7209dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt } 7309dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt 7409dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt mask = ~mask << (32 - prefix_length); 7509dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt mask = htonl(mask); 7609dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt 7709dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt return mask; 7809dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt} 7909dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt 8009dd819d2794caf1a17cd03592c100755fb25577Robert Greenwaltint ipv4NetmaskToPrefixLength(in_addr_t mask) 8109dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt{ 8209dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt int prefixLength = 0; 836ee3ecc03a7cf9118e6a0b2577f15c76244bc408Chris Dearman uint32_t m = (uint32_t)ntohl(mask); 8409dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt while (m & 0x80000000) { 8509dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt prefixLength++; 8609dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt m = m << 1; 8709dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt } 8809dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt return prefixLength; 8909dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt} 9009dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt 91c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczakstatic const char *ipaddr_to_string(in_addr_t addr) 92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct in_addr in_addr; 94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project in_addr.s_addr = addr; 96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return inet_ntoa(in_addr); 97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 9947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colittiint string_to_ip(const char *string, struct sockaddr_storage *ss) { 10047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct addrinfo hints, *ai; 10147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti int ret; 10247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 10347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (ss == NULL) { 10447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return -EFAULT; 10547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 10647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 10747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti memset(&hints, 0, sizeof(hints)); 10847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti hints.ai_family = AF_UNSPEC; 10947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti hints.ai_flags = AI_NUMERICHOST; 11047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti hints.ai_socktype = SOCK_DGRAM; 11147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 11247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti ret = getaddrinfo(string, NULL, &hints, &ai); 11347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (ret == 0) { 11447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti memcpy(ss, ai->ai_addr, ai->ai_addrlen); 11547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti freeaddrinfo(ai); 11647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 11747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 11847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return ret; 11947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti} 12047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_init(void) 122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 123b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int ret; 124cebcd450c6ca3de5106ef3d817d5b760f5d57fbeDmitry Shmidt 125cebcd450c6ca3de5106ef3d817d5b760f5d57fbeDmitry Shmidt pthread_mutex_lock(&ifc_sock_mutex); 126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ifc_ctl_sock == -1) { 1276d3cddb2e245738f0b78a758a83ebf2608865394Nick Kralevich ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); 128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ifc_ctl_sock < 0) { 129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printerr("socket() failed: %s\n", strerror(errno)); 130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 132b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt 133b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt ret = ifc_ctl_sock < 0 ? -1 : 0; 134b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (DBG) printerr("ifc_init_returning %d", ret); 135b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return ret; 136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1388984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naikint ifc_init6(void) 1398984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik{ 140cebcd450c6ca3de5106ef3d817d5b760f5d57fbeDmitry Shmidt pthread_mutex_lock(&ifc_sock6_mutex); 1418984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (ifc_ctl_sock6 == -1) { 1426d3cddb2e245738f0b78a758a83ebf2608865394Nick Kralevich ifc_ctl_sock6 = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0); 1438984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (ifc_ctl_sock6 < 0) { 1448984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik printerr("socket() failed: %s\n", strerror(errno)); 1458984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 1468984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 1478984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik return ifc_ctl_sock6 < 0 ? -1 : 0; 1488984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik} 1498984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid ifc_close(void) 151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 152b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (DBG) printerr("ifc_close"); 153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ifc_ctl_sock != -1) { 154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project (void)close(ifc_ctl_sock); 155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_ctl_sock = -1; 156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 157cebcd450c6ca3de5106ef3d817d5b760f5d57fbeDmitry Shmidt pthread_mutex_unlock(&ifc_sock_mutex); 158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1608984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naikvoid ifc_close6(void) 1618984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik{ 1628984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (ifc_ctl_sock6 != -1) { 1638984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik (void)close(ifc_ctl_sock6); 1648984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik ifc_ctl_sock6 = -1; 1658984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 166cebcd450c6ca3de5106ef3d817d5b760f5d57fbeDmitry Shmidt pthread_mutex_unlock(&ifc_sock6_mutex); 1678984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik} 1688984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void ifc_init_ifr(const char *name, struct ifreq *ifr) 170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(ifr, 0, sizeof(struct ifreq)); 172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project strncpy(ifr->ifr_name, name, IFNAMSIZ); 173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifr->ifr_name[IFNAMSIZ - 1] = 0; 174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_get_hwaddr(const char *name, void *ptr) 177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int r; 179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct ifreq ifr; 180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init_ifr(name, &ifr); 181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project r = ioctl(ifc_ctl_sock, SIOCGIFHWADDR, &ifr); 183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(r < 0) return -1; 184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 185c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak memcpy(ptr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN); 186b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return 0; 187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_get_ifindex(const char *name, int *if_indexp) 190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int r; 192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct ifreq ifr; 193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init_ifr(name, &ifr); 194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project r = ioctl(ifc_ctl_sock, SIOCGIFINDEX, &ifr); 196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(r < 0) return -1; 197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *if_indexp = ifr.ifr_ifindex; 1997d05a80da8c210d11df657bcec8b19a6bf1e8a16Dmitry Shmidt return 0; 200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int ifc_set_flags(const char *name, unsigned set, unsigned clr) 203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct ifreq ifr; 205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init_ifr(name, &ifr); 206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(ioctl(ifc_ctl_sock, SIOCGIFFLAGS, &ifr) < 0) return -1; 208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifr.ifr_flags = (ifr.ifr_flags & (~clr)) | set; 209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return ioctl(ifc_ctl_sock, SIOCSIFFLAGS, &ifr); 210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_up(const char *name) 213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 214b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int ret = ifc_set_flags(name, IFF_UP, 0); 215b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (DBG) printerr("ifc_up(%s) = %d", name, ret); 216b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return ret; 217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_down(const char *name) 220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 221b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int ret = ifc_set_flags(name, 0, IFF_UP); 222b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (DBG) printerr("ifc_down(%s) = %d", name, ret); 223b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return ret; 224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void init_sockaddr_in(struct sockaddr *sa, in_addr_t addr) 227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct sockaddr_in *sin = (struct sockaddr_in *) sa; 229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sin->sin_family = AF_INET; 230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sin->sin_port = 0; 231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sin->sin_addr.s_addr = addr; 232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_set_addr(const char *name, in_addr_t addr) 235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct ifreq ifr; 237b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int ret; 238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init_ifr(name, &ifr); 240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project init_sockaddr_in(&ifr.ifr_addr, addr); 2417d05a80da8c210d11df657bcec8b19a6bf1e8a16Dmitry Shmidt 242b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt ret = ioctl(ifc_ctl_sock, SIOCSIFADDR, &ifr); 243b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (DBG) printerr("ifc_set_addr(%s, xx) = %d", name, ret); 244b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return ret; 245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 24747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti/* 24847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * Adds or deletes an IP address on an interface. 24947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * 25047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * Action is one of: 25147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * - RTM_NEWADDR (to add a new address) 25247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * - RTM_DELADDR (to delete an existing address) 25347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * 25447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * Returns zero on success and negative errno on failure. 25547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti */ 25647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colittiint ifc_act_on_address(int action, const char *name, const char *address, 25747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti int prefixlen) { 25847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti int ifindex, s, len, ret; 25947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct sockaddr_storage ss; 260292997420c6fc385f31e568620476b0b71de97beBjorn Andersson int saved_errno; 26147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti void *addr; 26247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti size_t addrlen; 26347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct { 26447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct nlmsghdr n; 26547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct ifaddrmsg r; 26606cb8e92034274c6f803e97a17cd07fedf99bde5Erik Kline // Allow for IPv6 address, headers, IPv4 broadcast addr and padding. 26747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti char attrbuf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + 26847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti NLMSG_ALIGN(sizeof(struct rtattr)) + 26906cb8e92034274c6f803e97a17cd07fedf99bde5Erik Kline NLMSG_ALIGN(INET6_ADDRLEN) + 27006cb8e92034274c6f803e97a17cd07fedf99bde5Erik Kline NLMSG_ALIGN(sizeof(struct rtattr)) + 27106cb8e92034274c6f803e97a17cd07fedf99bde5Erik Kline NLMSG_ALIGN(INET_ADDRLEN)]; 27247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } req; 27347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct rtattr *rta; 27447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct nlmsghdr *nh; 27547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct nlmsgerr *err; 27647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti char buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + 27747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti NLMSG_ALIGN(sizeof(struct nlmsgerr)) + 27847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti NLMSG_ALIGN(sizeof(struct nlmsghdr))]; 27947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 28047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Get interface ID. 28147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti ifindex = if_nametoindex(name); 28247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (ifindex == 0) { 28347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return -errno; 28447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 28547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 28647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Convert string representation to sockaddr_storage. 28747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti ret = string_to_ip(address, &ss); 28847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (ret) { 28947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return ret; 29047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 29147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 29247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Determine address type and length. 29347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (ss.ss_family == AF_INET) { 29447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct sockaddr_in *sin = (struct sockaddr_in *) &ss; 29547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti addr = &sin->sin_addr; 29647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti addrlen = INET_ADDRLEN; 29747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } else if (ss.ss_family == AF_INET6) { 29847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &ss; 29947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti addr = &sin6->sin6_addr; 30047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti addrlen = INET6_ADDRLEN; 30147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } else { 30247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return -EAFNOSUPPORT; 30347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 30447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 30547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Fill in netlink structures. 30647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti memset(&req, 0, sizeof(req)); 30747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 30847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Netlink message header. 30947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.r)); 31047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti req.n.nlmsg_type = action; 31147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; 31247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti req.n.nlmsg_pid = getpid(); 31347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 31447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Interface address message header. 31547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti req.r.ifa_family = ss.ss_family; 31647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti req.r.ifa_prefixlen = prefixlen; 31747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti req.r.ifa_index = ifindex; 31847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 31947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Routing attribute. Contains the actual IP address. 32047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti rta = (struct rtattr *) (((char *) &req) + NLMSG_ALIGN(req.n.nlmsg_len)); 32147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti rta->rta_type = IFA_LOCAL; 32247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti rta->rta_len = RTA_LENGTH(addrlen); 32347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti req.n.nlmsg_len = NLMSG_ALIGN(req.n.nlmsg_len) + RTA_LENGTH(addrlen); 32447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti memcpy(RTA_DATA(rta), addr, addrlen); 32547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 32606cb8e92034274c6f803e97a17cd07fedf99bde5Erik Kline // Add an explicit IFA_BROADCAST for IPv4 RTM_NEWADDRs. 32706cb8e92034274c6f803e97a17cd07fedf99bde5Erik Kline if (ss.ss_family == AF_INET && action == RTM_NEWADDR) { 32806cb8e92034274c6f803e97a17cd07fedf99bde5Erik Kline rta = (struct rtattr *) (((char *) &req) + NLMSG_ALIGN(req.n.nlmsg_len)); 32906cb8e92034274c6f803e97a17cd07fedf99bde5Erik Kline rta->rta_type = IFA_BROADCAST; 33006cb8e92034274c6f803e97a17cd07fedf99bde5Erik Kline rta->rta_len = RTA_LENGTH(addrlen); 33106cb8e92034274c6f803e97a17cd07fedf99bde5Erik Kline req.n.nlmsg_len = NLMSG_ALIGN(req.n.nlmsg_len) + RTA_LENGTH(addrlen); 33206cb8e92034274c6f803e97a17cd07fedf99bde5Erik Kline ((struct in_addr *)addr)->s_addr |= htonl((1<<(32-prefixlen))-1); 33306cb8e92034274c6f803e97a17cd07fedf99bde5Erik Kline memcpy(RTA_DATA(rta), addr, addrlen); 33406cb8e92034274c6f803e97a17cd07fedf99bde5Erik Kline } 33506cb8e92034274c6f803e97a17cd07fedf99bde5Erik Kline 3366d3cddb2e245738f0b78a758a83ebf2608865394Nick Kralevich s = socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE); 337292997420c6fc385f31e568620476b0b71de97beBjorn Andersson if (s < 0) { 338292997420c6fc385f31e568620476b0b71de97beBjorn Andersson return -errno; 339292997420c6fc385f31e568620476b0b71de97beBjorn Andersson } 340292997420c6fc385f31e568620476b0b71de97beBjorn Andersson 34147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (send(s, &req, req.n.nlmsg_len, 0) < 0) { 342292997420c6fc385f31e568620476b0b71de97beBjorn Andersson saved_errno = errno; 34347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti close(s); 344292997420c6fc385f31e568620476b0b71de97beBjorn Andersson return -saved_errno; 34547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 34647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 34747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti len = recv(s, buf, sizeof(buf), 0); 348292997420c6fc385f31e568620476b0b71de97beBjorn Andersson saved_errno = errno; 34947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti close(s); 35047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (len < 0) { 351292997420c6fc385f31e568620476b0b71de97beBjorn Andersson return -saved_errno; 35247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 35347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 35447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Parse the acknowledgement to find the return code. 35547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti nh = (struct nlmsghdr *) buf; 35647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (!NLMSG_OK(nh, (unsigned) len) || nh->nlmsg_type != NLMSG_ERROR) { 35747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return -EINVAL; 35847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 35947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti err = NLMSG_DATA(nh); 36047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 36147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Return code is negative errno. 36247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return err->error; 36347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti} 36447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 36547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colittiint ifc_add_address(const char *name, const char *address, int prefixlen) { 36647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return ifc_act_on_address(RTM_NEWADDR, name, address, prefixlen); 36747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti} 36847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 36947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colittiint ifc_del_address(const char *name, const char * address, int prefixlen) { 37047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return ifc_act_on_address(RTM_DELADDR, name, address, prefixlen); 37147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti} 37247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 37347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti/* 37447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * Clears IPv6 addresses on the specified interface. 37547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti */ 37647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colittiint ifc_clear_ipv6_addresses(const char *name) { 37747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti char rawaddrstr[INET6_ADDRSTRLEN], addrstr[INET6_ADDRSTRLEN]; 37847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti unsigned int prefixlen; 37947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti int lasterror = 0, i, j, ret; 38047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti char ifname[64]; // Currently, IFNAMSIZ = 16. 38147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti FILE *f = fopen("/proc/net/if_inet6", "r"); 38247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (!f) { 38347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return -errno; 38447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 38547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 38647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Format: 38747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // 20010db8000a0001fc446aa4b5b347ed 03 40 00 01 wlan0 38847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti while (fscanf(f, "%32s %*02x %02x %*02x %*02x %63s\n", 38947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti rawaddrstr, &prefixlen, ifname) == 3) { 39047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Is this the interface we're looking for? 39147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (strcmp(name, ifname)) { 39247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti continue; 39347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 39447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 39547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Put the colons back into the address. 39647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti for (i = 0, j = 0; i < 32; i++, j++) { 39747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti addrstr[j] = rawaddrstr[i]; 39847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (i % 4 == 3) { 39947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti addrstr[++j] = ':'; 40047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 40147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 40247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti addrstr[j - 1] = '\0'; 40347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 40447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Don't delete the link-local address as well, or it will disable IPv6 40547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // on the interface. 40647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (strncmp(addrstr, "fe80:", 5) == 0) { 40747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti continue; 40847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 40947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 41047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti ret = ifc_del_address(ifname, addrstr, prefixlen); 41147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (ret) { 41201dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block ALOGE("Deleting address %s/%d on %s: %s", addrstr, prefixlen, ifname, 41347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti strerror(-ret)); 41447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti lasterror = ret; 41547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 41647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 41747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 41847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti fclose(f); 41947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return lasterror; 42047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti} 42147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 42247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti/* 42347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * Clears IPv4 addresses on the specified interface. 42447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti */ 42547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colittivoid ifc_clear_ipv4_addresses(const char *name) { 42647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti unsigned count, addr; 42747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti ifc_init(); 42847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti for (count=0, addr=1;((addr != 0) && (count < 255)); count++) { 42947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (ifc_get_addr(name, &addr) < 0) 43047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti break; 43147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (addr) 43247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti ifc_set_addr(name, 0); 43347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 43447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti ifc_close(); 43547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti} 43647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 43747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti/* 43847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * Clears all IP addresses on the specified interface. 43947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti */ 44047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colittiint ifc_clear_addresses(const char *name) { 44147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti ifc_clear_ipv4_addresses(name); 44247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return ifc_clear_ipv6_addresses(name); 44347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti} 44447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 445c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczakint ifc_set_hwaddr(const char *name, const void *ptr) 446c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak{ 447c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak struct ifreq ifr; 448c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak ifc_init_ifr(name, &ifr); 449c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak 450c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER; 451c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak memcpy(&ifr.ifr_hwaddr.sa_data, ptr, ETH_ALEN); 452c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak return ioctl(ifc_ctl_sock, SIOCSIFHWADDR, &ifr); 453c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak} 454c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak 4556f49d5f266dffee103a3af07a7f6266f405d2924Jake Hambyint ifc_set_mask(const char *name, in_addr_t mask) 4566f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby{ 4576f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby struct ifreq ifr; 458b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int ret; 4596f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby 4606f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby ifc_init_ifr(name, &ifr); 4616f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby init_sockaddr_in(&ifr.ifr_addr, mask); 4626f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby 463b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt ret = ioctl(ifc_ctl_sock, SIOCSIFNETMASK, &ifr); 464b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (DBG) printerr("ifc_set_mask(%s, xx) = %d", name, ret); 465b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return ret; 4666f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby} 4676f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby 46809dd819d2794caf1a17cd03592c100755fb25577Robert Greenwaltint ifc_set_prefixLength(const char *name, int prefixLength) 469dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 470dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct ifreq ifr; 47109dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt // TODO - support ipv6 47209dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt if (prefixLength > 32 || prefixLength < 0) return -1; 473dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 47409dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt in_addr_t mask = prefixLengthToIpv4Netmask(prefixLength); 475dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init_ifr(name, &ifr); 476dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project init_sockaddr_in(&ifr.ifr_addr, mask); 4777d05a80da8c210d11df657bcec8b19a6bf1e8a16Dmitry Shmidt 478dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return ioctl(ifc_ctl_sock, SIOCSIFNETMASK, &ifr); 479dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 480dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 4819092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidtint ifc_get_addr(const char *name, in_addr_t *addr) 4829092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt{ 4839092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt struct ifreq ifr; 4849092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt int ret = 0; 4859092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt 4869092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt ifc_init_ifr(name, &ifr); 4879092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt if (addr != NULL) { 4889092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt ret = ioctl(ifc_ctl_sock, SIOCGIFADDR, &ifr); 4899092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt if (ret < 0) { 4909092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt *addr = 0; 4919092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt } else { 4929092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt *addr = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr; 4939092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt } 4949092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt } 4959092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt return ret; 4969092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt} 4979092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt 49809dd819d2794caf1a17cd03592c100755fb25577Robert Greenwaltint ifc_get_info(const char *name, in_addr_t *addr, int *prefixLength, unsigned *flags) 499dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 500dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct ifreq ifr; 501dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init_ifr(name, &ifr); 502dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 503dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (addr != NULL) { 504dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(ioctl(ifc_ctl_sock, SIOCGIFADDR, &ifr) < 0) { 505dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *addr = 0; 506dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 507dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *addr = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr; 508dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 509dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 5107d05a80da8c210d11df657bcec8b19a6bf1e8a16Dmitry Shmidt 51109dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt if (prefixLength != NULL) { 512dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(ioctl(ifc_ctl_sock, SIOCGIFNETMASK, &ifr) < 0) { 51309dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt *prefixLength = 0; 514dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 5156ee3ecc03a7cf9118e6a0b2577f15c76244bc408Chris Dearman *prefixLength = ipv4NetmaskToPrefixLength( 51609dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr); 517dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 518dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 519dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 520dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (flags != NULL) { 521dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(ioctl(ifc_ctl_sock, SIOCGIFFLAGS, &ifr) < 0) { 522dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *flags = 0; 523dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 524dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *flags = ifr.ifr_flags; 525dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 526dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 527dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 528dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 529dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 530dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 531021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwaltint ifc_act_on_ipv4_route(int action, const char *ifname, struct in_addr dst, int prefix_length, 5328984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik struct in_addr gw) 533dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 534dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct rtentry rt; 535dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int result; 5368984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik in_addr_t netmask; 537dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 538dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(&rt, 0, sizeof(rt)); 5398984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 540dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project rt.rt_dst.sa_family = AF_INET; 5418984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik rt.rt_dev = (void*) ifname; 5428984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 54309dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt netmask = prefixLengthToIpv4Netmask(prefix_length); 5448984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik init_sockaddr_in(&rt.rt_genmask, netmask); 5458984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik init_sockaddr_in(&rt.rt_dst, dst.s_addr); 5468984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik rt.rt_flags = RTF_UP; 5478984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 5488984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (prefix_length == 32) { 5498984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik rt.rt_flags |= RTF_HOST; 5508984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 5518984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 5528984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (gw.s_addr != 0) { 5538984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik rt.rt_flags |= RTF_GATEWAY; 5548984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik init_sockaddr_in(&rt.rt_gateway, gw.s_addr); 5558984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 5568984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 557dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init(); 5588984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 5598984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (ifc_ctl_sock < 0) { 560cebcd450c6ca3de5106ef3d817d5b760f5d57fbeDmitry Shmidt ifc_close(); 5618984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik return -errno; 5628984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 5638984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 564021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt result = ioctl(ifc_ctl_sock, action, &rt); 5658984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (result < 0) { 5668984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (errno == EEXIST) { 5678984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik result = 0; 5688984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } else { 5698984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik result = -errno; 5708984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 571dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 572dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_close(); 573dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return result; 574dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 575dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 576b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt/* deprecated - v4 only */ 5778984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naikint ifc_create_default_route(const char *name, in_addr_t gw) 5788984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik{ 5798984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik struct in_addr in_dst, in_gw; 5808984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 5818984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik in_dst.s_addr = 0; 5828984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik in_gw.s_addr = gw; 5838984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 584b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int ret = ifc_act_on_ipv4_route(SIOCADDRT, name, in_dst, 0, in_gw); 585b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (DBG) printerr("ifc_create_default_route(%s, %d) = %d", name, gw, ret); 586b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return ret; 587b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt} 588b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt 589eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran// Needed by code in hidden partner repositories / branches, so don't delete. 590eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandranint ifc_enable(const char *ifname) 591eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran{ 592eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran int result; 593eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran 594eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran ifc_init(); 595eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran result = ifc_up(ifname); 596eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran ifc_close(); 597eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran return result; 598eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran} 599eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran 600e5ab3e3a4c23077ede0515320c5585a99b236671Sreeram Ramachandran// Needed by code in hidden partner repositories / branches, so don't delete. 601eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandranint ifc_disable(const char *ifname) 602eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran{ 603eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran unsigned addr, count; 604eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran int result; 605eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran 606eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran ifc_init(); 607eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran result = ifc_down(ifname); 608eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran 609eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran ifc_set_addr(ifname, 0); 610eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran for (count=0, addr=1;((addr != 0) && (count < 255)); count++) { 611eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran if (ifc_get_addr(ifname, &addr) < 0) 612eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran break; 613eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran if (addr) 614eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran ifc_set_addr(ifname, 0); 615eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran } 616eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran 617eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran ifc_close(); 618eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran return result; 619eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran} 620eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran 621979203ee34084327bf4f20ad1f878450de94826eWink Savilleint ifc_reset_connections(const char *ifname, const int reset_mask) 622dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 6239b828adfad09200f3f1bd3602187fe3dd5335774Elliott Hughes#if defined(__ANDROID__) 6246cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti int result, success; 62517622d09d5ba54ae3c8b11644c6d7556bdc6644cSreeram Ramachandran in_addr_t myaddr = 0; 626dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct ifreq ifr; 6276cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti struct in6_ifreq ifr6; 628dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 629979203ee34084327bf4f20ad1f878450de94826eWink Saville if (reset_mask & RESET_IPV4_ADDRESSES) { 630979203ee34084327bf4f20ad1f878450de94826eWink Saville /* IPv4. Clear connections on the IP address. */ 631979203ee34084327bf4f20ad1f878450de94826eWink Saville ifc_init(); 63217622d09d5ba54ae3c8b11644c6d7556bdc6644cSreeram Ramachandran if (!(reset_mask & RESET_IGNORE_INTERFACE_ADDRESS)) { 63317622d09d5ba54ae3c8b11644c6d7556bdc6644cSreeram Ramachandran ifc_get_info(ifname, &myaddr, NULL, NULL); 63417622d09d5ba54ae3c8b11644c6d7556bdc6644cSreeram Ramachandran } 635979203ee34084327bf4f20ad1f878450de94826eWink Saville ifc_init_ifr(ifname, &ifr); 636979203ee34084327bf4f20ad1f878450de94826eWink Saville init_sockaddr_in(&ifr.ifr_addr, myaddr); 637979203ee34084327bf4f20ad1f878450de94826eWink Saville result = ioctl(ifc_ctl_sock, SIOCKILLADDR, &ifr); 638979203ee34084327bf4f20ad1f878450de94826eWink Saville ifc_close(); 639979203ee34084327bf4f20ad1f878450de94826eWink Saville } else { 640979203ee34084327bf4f20ad1f878450de94826eWink Saville result = 0; 641979203ee34084327bf4f20ad1f878450de94826eWink Saville } 6427d05a80da8c210d11df657bcec8b19a6bf1e8a16Dmitry Shmidt 643979203ee34084327bf4f20ad1f878450de94826eWink Saville if (reset_mask & RESET_IPV6_ADDRESSES) { 644979203ee34084327bf4f20ad1f878450de94826eWink Saville /* 645979203ee34084327bf4f20ad1f878450de94826eWink Saville * IPv6. On Linux, when an interface goes down it loses all its IPv6 646979203ee34084327bf4f20ad1f878450de94826eWink Saville * addresses, so we don't know which connections belonged to that interface 647979203ee34084327bf4f20ad1f878450de94826eWink Saville * So we clear all unused IPv6 connections on the device by specifying an 648979203ee34084327bf4f20ad1f878450de94826eWink Saville * empty IPv6 address. 649979203ee34084327bf4f20ad1f878450de94826eWink Saville */ 650979203ee34084327bf4f20ad1f878450de94826eWink Saville ifc_init6(); 651979203ee34084327bf4f20ad1f878450de94826eWink Saville // This implicitly specifies an address of ::, i.e., kill all IPv6 sockets. 652979203ee34084327bf4f20ad1f878450de94826eWink Saville memset(&ifr6, 0, sizeof(ifr6)); 653979203ee34084327bf4f20ad1f878450de94826eWink Saville success = ioctl(ifc_ctl_sock6, SIOCKILLADDR, &ifr6); 654979203ee34084327bf4f20ad1f878450de94826eWink Saville if (result == 0) { 655979203ee34084327bf4f20ad1f878450de94826eWink Saville result = success; 656979203ee34084327bf4f20ad1f878450de94826eWink Saville } 657979203ee34084327bf4f20ad1f878450de94826eWink Saville ifc_close6(); 6586cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti } 6596cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti 660dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return result; 661dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else 662dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 663dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 664dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 665dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 666c463025a19aff3f9f92cffa3de6462316e8407a7Elliott Hughes/* 667c463025a19aff3f9f92cffa3de6462316e8407a7Elliott Hughes * Removes the default route for the named interface. 668c463025a19aff3f9f92cffa3de6462316e8407a7Elliott Hughes */ 669c463025a19aff3f9f92cffa3de6462316e8407a7Elliott Hughesint ifc_remove_default_route(const char *ifname) 670c463025a19aff3f9f92cffa3de6462316e8407a7Elliott Hughes{ 671c463025a19aff3f9f92cffa3de6462316e8407a7Elliott Hughes struct rtentry rt; 672c463025a19aff3f9f92cffa3de6462316e8407a7Elliott Hughes int result; 673c463025a19aff3f9f92cffa3de6462316e8407a7Elliott Hughes 674c463025a19aff3f9f92cffa3de6462316e8407a7Elliott Hughes ifc_init(); 675c463025a19aff3f9f92cffa3de6462316e8407a7Elliott Hughes memset(&rt, 0, sizeof(rt)); 676c463025a19aff3f9f92cffa3de6462316e8407a7Elliott Hughes rt.rt_dev = (void *)ifname; 677c463025a19aff3f9f92cffa3de6462316e8407a7Elliott Hughes rt.rt_flags = RTF_UP|RTF_GATEWAY; 678c463025a19aff3f9f92cffa3de6462316e8407a7Elliott Hughes init_sockaddr_in(&rt.rt_dst, 0); 679c463025a19aff3f9f92cffa3de6462316e8407a7Elliott Hughes if ((result = ioctl(ifc_ctl_sock, SIOCDELRT, &rt)) < 0) { 680c463025a19aff3f9f92cffa3de6462316e8407a7Elliott Hughes ALOGD("failed to remove default route for %s: %s", ifname, strerror(errno)); 681c463025a19aff3f9f92cffa3de6462316e8407a7Elliott Hughes } 682c463025a19aff3f9f92cffa3de6462316e8407a7Elliott Hughes ifc_close(); 683c463025a19aff3f9f92cffa3de6462316e8407a7Elliott Hughes return result; 684c463025a19aff3f9f92cffa3de6462316e8407a7Elliott Hughes} 685c463025a19aff3f9f92cffa3de6462316e8407a7Elliott Hughes 686dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint 687dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectifc_configure(const char *ifname, 688dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project in_addr_t address, 68909dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt uint32_t prefixLength, 690dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project in_addr_t gateway, 691dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project in_addr_t dns1, 692dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project in_addr_t dns2) { 693dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 694dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char dns_prop_name[PROPERTY_KEY_MAX]; 695dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 696dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init(); 697dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 698dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ifc_up(ifname)) { 699dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printerr("failed to turn on interface %s: %s\n", ifname, strerror(errno)); 700dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_close(); 701dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 702dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 703dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ifc_set_addr(ifname, address)) { 704dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printerr("failed to set ipaddr %s: %s\n", ipaddr_to_string(address), strerror(errno)); 705dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_close(); 706dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 707dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 70809dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt if (ifc_set_prefixLength(ifname, prefixLength)) { 70909dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt printerr("failed to set prefixLength %d: %s\n", prefixLength, strerror(errno)); 710dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_close(); 711dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 712dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 713dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ifc_create_default_route(ifname, gateway)) { 714dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printerr("failed to set default route %s: %s\n", ipaddr_to_string(gateway), strerror(errno)); 715dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_close(); 716dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 717dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 718dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 719dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_close(); 720dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 721c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns1", ifname); 722dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project property_set(dns_prop_name, dns1 ? ipaddr_to_string(dns1) : ""); 723c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns2", ifname); 724dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project property_set(dns_prop_name, dns2 ? ipaddr_to_string(dns2) : ""); 725dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 726dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 727dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 728