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 532d640c2640b957f704d86fcaea6e5a4af54dde2cElliott Hughes#ifdef HAVE_ANDROID_OS 542d640c2640b957f704d86fcaea6e5a4af54dde2cElliott Hughes/* SIOCKILLADDR is an Android extension. */ 552d640c2640b957f704d86fcaea6e5a4af54dde2cElliott Hughes#define SIOCKILLADDR 0x8939 562d640c2640b957f704d86fcaea6e5a4af54dde2cElliott Hughes#endif 572d640c2640b957f704d86fcaea6e5a4af54dde2cElliott Hughes 58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int ifc_ctl_sock = -1; 598984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naikstatic int ifc_ctl_sock6 = -1; 60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid printerr(char *fmt, ...); 61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 62b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt#define DBG 0 6347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti#define INET_ADDRLEN 4 6447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti#define INET6_ADDRLEN 16 65b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt 6609dd819d2794caf1a17cd03592c100755fb25577Robert Greenwaltin_addr_t prefixLengthToIpv4Netmask(int prefix_length) 6709dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt{ 6809dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt in_addr_t mask = 0; 6909dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt 7009dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt // C99 (6.5.7): shifts of 32 bits have undefined results 7109dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt if (prefix_length <= 0 || prefix_length > 32) { 7209dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt return 0; 7309dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt } 7409dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt 7509dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt mask = ~mask << (32 - prefix_length); 7609dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt mask = htonl(mask); 7709dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt 7809dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt return mask; 7909dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt} 8009dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt 8109dd819d2794caf1a17cd03592c100755fb25577Robert Greenwaltint ipv4NetmaskToPrefixLength(in_addr_t mask) 8209dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt{ 8309dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt int prefixLength = 0; 846ee3ecc03a7cf9118e6a0b2577f15c76244bc408Chris Dearman uint32_t m = (uint32_t)ntohl(mask); 8509dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt while (m & 0x80000000) { 8609dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt prefixLength++; 8709dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt m = m << 1; 8809dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt } 8909dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt return prefixLength; 9009dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt} 9109dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt 92c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczakstatic const char *ipaddr_to_string(in_addr_t addr) 93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct in_addr in_addr; 95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project in_addr.s_addr = addr; 97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return inet_ntoa(in_addr); 98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 10047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colittiint string_to_ip(const char *string, struct sockaddr_storage *ss) { 10147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct addrinfo hints, *ai; 10247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti int ret; 10347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 10447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (ss == NULL) { 10547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return -EFAULT; 10647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 10747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 10847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti memset(&hints, 0, sizeof(hints)); 10947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti hints.ai_family = AF_UNSPEC; 11047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti hints.ai_flags = AI_NUMERICHOST; 11147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti hints.ai_socktype = SOCK_DGRAM; 11247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 11347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti ret = getaddrinfo(string, NULL, &hints, &ai); 11447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (ret == 0) { 11547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti memcpy(ss, ai->ai_addr, ai->ai_addrlen); 11647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti freeaddrinfo(ai); 11747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 11847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 11947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return ret; 12047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti} 12147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_init(void) 123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 124b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int ret; 125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ifc_ctl_sock == -1) { 126b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM, 0); 127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ifc_ctl_sock < 0) { 128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printerr("socket() failed: %s\n", strerror(errno)); 129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 131b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt 132b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt ret = ifc_ctl_sock < 0 ? -1 : 0; 133b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (DBG) printerr("ifc_init_returning %d", ret); 134b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return ret; 135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1378984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naikint ifc_init6(void) 1388984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik{ 1398984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (ifc_ctl_sock6 == -1) { 1408984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik ifc_ctl_sock6 = socket(AF_INET6, SOCK_DGRAM, 0); 1418984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (ifc_ctl_sock6 < 0) { 1428984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik printerr("socket() failed: %s\n", strerror(errno)); 1438984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 1448984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 1458984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik return ifc_ctl_sock6 < 0 ? -1 : 0; 1468984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik} 1478984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid ifc_close(void) 149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 150b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (DBG) printerr("ifc_close"); 151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ifc_ctl_sock != -1) { 152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project (void)close(ifc_ctl_sock); 153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_ctl_sock = -1; 154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1578984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naikvoid ifc_close6(void) 1588984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik{ 1598984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (ifc_ctl_sock6 != -1) { 1608984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik (void)close(ifc_ctl_sock6); 1618984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik ifc_ctl_sock6 = -1; 1628984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 1638984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik} 1648984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void ifc_init_ifr(const char *name, struct ifreq *ifr) 166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(ifr, 0, sizeof(struct ifreq)); 168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project strncpy(ifr->ifr_name, name, IFNAMSIZ); 169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifr->ifr_name[IFNAMSIZ - 1] = 0; 170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_get_hwaddr(const char *name, void *ptr) 173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int r; 175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct ifreq ifr; 176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init_ifr(name, &ifr); 177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project r = ioctl(ifc_ctl_sock, SIOCGIFHWADDR, &ifr); 179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(r < 0) return -1; 180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 181c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak memcpy(ptr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN); 182b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return 0; 183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_get_ifindex(const char *name, int *if_indexp) 186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int r; 188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct ifreq ifr; 189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init_ifr(name, &ifr); 190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project r = ioctl(ifc_ctl_sock, SIOCGIFINDEX, &ifr); 192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(r < 0) return -1; 193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *if_indexp = ifr.ifr_ifindex; 1957d05a80da8c210d11df657bcec8b19a6bf1e8a16Dmitry Shmidt return 0; 196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int ifc_set_flags(const char *name, unsigned set, unsigned clr) 199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct ifreq ifr; 201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init_ifr(name, &ifr); 202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(ioctl(ifc_ctl_sock, SIOCGIFFLAGS, &ifr) < 0) return -1; 204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifr.ifr_flags = (ifr.ifr_flags & (~clr)) | set; 205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return ioctl(ifc_ctl_sock, SIOCSIFFLAGS, &ifr); 206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_up(const char *name) 209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 210b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int ret = ifc_set_flags(name, IFF_UP, 0); 211b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (DBG) printerr("ifc_up(%s) = %d", name, ret); 212b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return ret; 213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_down(const char *name) 216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 217b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int ret = ifc_set_flags(name, 0, IFF_UP); 218b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (DBG) printerr("ifc_down(%s) = %d", name, ret); 219b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return ret; 220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void init_sockaddr_in(struct sockaddr *sa, in_addr_t addr) 223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct sockaddr_in *sin = (struct sockaddr_in *) sa; 225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sin->sin_family = AF_INET; 226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sin->sin_port = 0; 227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sin->sin_addr.s_addr = addr; 228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_set_addr(const char *name, in_addr_t addr) 231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct ifreq ifr; 233b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int ret; 234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init_ifr(name, &ifr); 236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project init_sockaddr_in(&ifr.ifr_addr, addr); 2377d05a80da8c210d11df657bcec8b19a6bf1e8a16Dmitry Shmidt 238b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt ret = ioctl(ifc_ctl_sock, SIOCSIFADDR, &ifr); 239b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (DBG) printerr("ifc_set_addr(%s, xx) = %d", name, ret); 240b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return ret; 241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 24347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti/* 24447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * Adds or deletes an IP address on an interface. 24547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * 24647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * Action is one of: 24747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * - RTM_NEWADDR (to add a new address) 24847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * - RTM_DELADDR (to delete an existing address) 24947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * 25047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * Returns zero on success and negative errno on failure. 25147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti */ 25247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colittiint ifc_act_on_address(int action, const char *name, const char *address, 25347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti int prefixlen) { 25447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti int ifindex, s, len, ret; 25547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct sockaddr_storage ss; 25647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti void *addr; 25747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti size_t addrlen; 25847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct { 25947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct nlmsghdr n; 26047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct ifaddrmsg r; 26147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Allow for IPv6 address, headers, and padding. 26247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti char attrbuf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + 26347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti NLMSG_ALIGN(sizeof(struct rtattr)) + 26447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti NLMSG_ALIGN(INET6_ADDRLEN)]; 26547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } req; 26647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct rtattr *rta; 26747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct nlmsghdr *nh; 26847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct nlmsgerr *err; 26947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti char buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + 27047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti NLMSG_ALIGN(sizeof(struct nlmsgerr)) + 27147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti NLMSG_ALIGN(sizeof(struct nlmsghdr))]; 27247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 27347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Get interface ID. 27447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti ifindex = if_nametoindex(name); 27547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (ifindex == 0) { 27647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return -errno; 27747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 27847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 27947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Convert string representation to sockaddr_storage. 28047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti ret = string_to_ip(address, &ss); 28147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (ret) { 28247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return ret; 28347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 28447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 28547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Determine address type and length. 28647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (ss.ss_family == AF_INET) { 28747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct sockaddr_in *sin = (struct sockaddr_in *) &ss; 28847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti addr = &sin->sin_addr; 28947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti addrlen = INET_ADDRLEN; 29047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } else if (ss.ss_family == AF_INET6) { 29147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &ss; 29247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti addr = &sin6->sin6_addr; 29347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti addrlen = INET6_ADDRLEN; 29447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } else { 29547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return -EAFNOSUPPORT; 29647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 29747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 29847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Fill in netlink structures. 29947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti memset(&req, 0, sizeof(req)); 30047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 30147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Netlink message header. 30247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.r)); 30347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti req.n.nlmsg_type = action; 30447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; 30547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti req.n.nlmsg_pid = getpid(); 30647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 30747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Interface address message header. 30847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti req.r.ifa_family = ss.ss_family; 30947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti req.r.ifa_prefixlen = prefixlen; 31047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti req.r.ifa_index = ifindex; 31147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 31247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Routing attribute. Contains the actual IP address. 31347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti rta = (struct rtattr *) (((char *) &req) + NLMSG_ALIGN(req.n.nlmsg_len)); 31447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti rta->rta_type = IFA_LOCAL; 31547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti rta->rta_len = RTA_LENGTH(addrlen); 31647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti req.n.nlmsg_len = NLMSG_ALIGN(req.n.nlmsg_len) + RTA_LENGTH(addrlen); 31747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti memcpy(RTA_DATA(rta), addr, addrlen); 31847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 31947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); 32047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (send(s, &req, req.n.nlmsg_len, 0) < 0) { 32147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti close(s); 32247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return -errno; 32347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 32447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 32547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti len = recv(s, buf, sizeof(buf), 0); 32647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti close(s); 32747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (len < 0) { 32847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return -errno; 32947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 33047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 33147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Parse the acknowledgement to find the return code. 33247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti nh = (struct nlmsghdr *) buf; 33347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (!NLMSG_OK(nh, (unsigned) len) || nh->nlmsg_type != NLMSG_ERROR) { 33447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return -EINVAL; 33547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 33647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti err = NLMSG_DATA(nh); 33747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 33847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Return code is negative errno. 33947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return err->error; 34047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti} 34147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 34247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colittiint ifc_add_address(const char *name, const char *address, int prefixlen) { 34347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return ifc_act_on_address(RTM_NEWADDR, name, address, prefixlen); 34447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti} 34547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 34647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colittiint ifc_del_address(const char *name, const char * address, int prefixlen) { 34747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return ifc_act_on_address(RTM_DELADDR, name, address, prefixlen); 34847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti} 34947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 35047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti/* 35147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * Clears IPv6 addresses on the specified interface. 35247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti */ 35347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colittiint ifc_clear_ipv6_addresses(const char *name) { 35447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti char rawaddrstr[INET6_ADDRSTRLEN], addrstr[INET6_ADDRSTRLEN]; 35547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti unsigned int prefixlen; 35647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti int lasterror = 0, i, j, ret; 35747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti char ifname[64]; // Currently, IFNAMSIZ = 16. 35847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti FILE *f = fopen("/proc/net/if_inet6", "r"); 35947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (!f) { 36047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return -errno; 36147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 36247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 36347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Format: 36447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // 20010db8000a0001fc446aa4b5b347ed 03 40 00 01 wlan0 36547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti while (fscanf(f, "%32s %*02x %02x %*02x %*02x %63s\n", 36647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti rawaddrstr, &prefixlen, ifname) == 3) { 36747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Is this the interface we're looking for? 36847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (strcmp(name, ifname)) { 36947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti continue; 37047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 37147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 37247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Put the colons back into the address. 37347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti for (i = 0, j = 0; i < 32; i++, j++) { 37447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti addrstr[j] = rawaddrstr[i]; 37547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (i % 4 == 3) { 37647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti addrstr[++j] = ':'; 37747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 37847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 37947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti addrstr[j - 1] = '\0'; 38047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 38147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Don't delete the link-local address as well, or it will disable IPv6 38247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // on the interface. 38347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (strncmp(addrstr, "fe80:", 5) == 0) { 38447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti continue; 38547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 38647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 38747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti ret = ifc_del_address(ifname, addrstr, prefixlen); 38847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (ret) { 38901dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block ALOGE("Deleting address %s/%d on %s: %s", addrstr, prefixlen, ifname, 39047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti strerror(-ret)); 39147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti lasterror = ret; 39247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 39347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 39447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 39547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti fclose(f); 39647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return lasterror; 39747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti} 39847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 39947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti/* 40047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * Clears IPv4 addresses on the specified interface. 40147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti */ 40247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colittivoid ifc_clear_ipv4_addresses(const char *name) { 40347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti unsigned count, addr; 40447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti ifc_init(); 40547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti for (count=0, addr=1;((addr != 0) && (count < 255)); count++) { 40647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (ifc_get_addr(name, &addr) < 0) 40747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti break; 40847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (addr) 40947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti ifc_set_addr(name, 0); 41047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 41147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti ifc_close(); 41247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti} 41347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 41447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti/* 41547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * Clears all IP addresses on the specified interface. 41647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti */ 41747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colittiint ifc_clear_addresses(const char *name) { 41847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti ifc_clear_ipv4_addresses(name); 41947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return ifc_clear_ipv6_addresses(name); 42047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti} 42147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 422c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczakint ifc_set_hwaddr(const char *name, const void *ptr) 423c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak{ 424c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak int r; 425c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak struct ifreq ifr; 426c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak ifc_init_ifr(name, &ifr); 427c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak 428c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER; 429c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak memcpy(&ifr.ifr_hwaddr.sa_data, ptr, ETH_ALEN); 430c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak return ioctl(ifc_ctl_sock, SIOCSIFHWADDR, &ifr); 431c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak} 432c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak 4336f49d5f266dffee103a3af07a7f6266f405d2924Jake Hambyint ifc_set_mask(const char *name, in_addr_t mask) 4346f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby{ 4356f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby struct ifreq ifr; 436b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int ret; 4376f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby 4386f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby ifc_init_ifr(name, &ifr); 4396f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby init_sockaddr_in(&ifr.ifr_addr, mask); 4406f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby 441b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt ret = ioctl(ifc_ctl_sock, SIOCSIFNETMASK, &ifr); 442b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (DBG) printerr("ifc_set_mask(%s, xx) = %d", name, ret); 443b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return ret; 4446f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby} 4456f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby 44609dd819d2794caf1a17cd03592c100755fb25577Robert Greenwaltint ifc_set_prefixLength(const char *name, int prefixLength) 447dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 448dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct ifreq ifr; 44909dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt // TODO - support ipv6 45009dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt if (prefixLength > 32 || prefixLength < 0) return -1; 451dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 45209dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt in_addr_t mask = prefixLengthToIpv4Netmask(prefixLength); 453dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init_ifr(name, &ifr); 454dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project init_sockaddr_in(&ifr.ifr_addr, mask); 4557d05a80da8c210d11df657bcec8b19a6bf1e8a16Dmitry Shmidt 456dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return ioctl(ifc_ctl_sock, SIOCSIFNETMASK, &ifr); 457dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 4599092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidtint ifc_get_addr(const char *name, in_addr_t *addr) 4609092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt{ 4619092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt struct ifreq ifr; 4629092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt int ret = 0; 4639092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt 4649092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt ifc_init_ifr(name, &ifr); 4659092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt if (addr != NULL) { 4669092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt ret = ioctl(ifc_ctl_sock, SIOCGIFADDR, &ifr); 4679092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt if (ret < 0) { 4689092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt *addr = 0; 4699092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt } else { 4709092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt *addr = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr; 4719092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt } 4729092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt } 4739092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt return ret; 4749092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt} 4759092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt 47609dd819d2794caf1a17cd03592c100755fb25577Robert Greenwaltint ifc_get_info(const char *name, in_addr_t *addr, int *prefixLength, unsigned *flags) 477dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 478dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct ifreq ifr; 479dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init_ifr(name, &ifr); 480dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 481dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (addr != NULL) { 482dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(ioctl(ifc_ctl_sock, SIOCGIFADDR, &ifr) < 0) { 483dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *addr = 0; 484dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 485dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *addr = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr; 486dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 487dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 4887d05a80da8c210d11df657bcec8b19a6bf1e8a16Dmitry Shmidt 48909dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt if (prefixLength != NULL) { 490dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(ioctl(ifc_ctl_sock, SIOCGIFNETMASK, &ifr) < 0) { 49109dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt *prefixLength = 0; 492dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 4936ee3ecc03a7cf9118e6a0b2577f15c76244bc408Chris Dearman *prefixLength = ipv4NetmaskToPrefixLength( 49409dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr); 495dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 496dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 497dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 498dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (flags != NULL) { 499dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(ioctl(ifc_ctl_sock, SIOCGIFFLAGS, &ifr) < 0) { 500dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *flags = 0; 501dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 502dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *flags = ifr.ifr_flags; 503dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 504dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 505dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 506dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 507dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 508dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 509021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwaltint ifc_act_on_ipv4_route(int action, const char *ifname, struct in_addr dst, int prefix_length, 5108984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik struct in_addr gw) 511dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 512dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct rtentry rt; 513dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int result; 5148984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik in_addr_t netmask; 515dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 516dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(&rt, 0, sizeof(rt)); 5178984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 518dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project rt.rt_dst.sa_family = AF_INET; 5198984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik rt.rt_dev = (void*) ifname; 5208984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 52109dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt netmask = prefixLengthToIpv4Netmask(prefix_length); 5228984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik init_sockaddr_in(&rt.rt_genmask, netmask); 5238984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik init_sockaddr_in(&rt.rt_dst, dst.s_addr); 5248984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik rt.rt_flags = RTF_UP; 5258984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 5268984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (prefix_length == 32) { 5278984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik rt.rt_flags |= RTF_HOST; 5288984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 5298984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 5308984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (gw.s_addr != 0) { 5318984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik rt.rt_flags |= RTF_GATEWAY; 5328984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik init_sockaddr_in(&rt.rt_gateway, gw.s_addr); 5338984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 5348984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 535dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init(); 5368984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 5378984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (ifc_ctl_sock < 0) { 5388984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik return -errno; 5398984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 5408984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 541021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt result = ioctl(ifc_ctl_sock, action, &rt); 5428984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (result < 0) { 5438984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (errno == EEXIST) { 5448984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik result = 0; 5458984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } else { 5468984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik result = -errno; 5478984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 548dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 549dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_close(); 550dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return result; 551dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 552dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 553b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt/* deprecated - v4 only */ 5548984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naikint ifc_create_default_route(const char *name, in_addr_t gw) 5558984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik{ 5568984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik struct in_addr in_dst, in_gw; 5578984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 5588984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik in_dst.s_addr = 0; 5598984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik in_gw.s_addr = gw; 5608984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 561b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int ret = ifc_act_on_ipv4_route(SIOCADDRT, name, in_dst, 0, in_gw); 562b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (DBG) printerr("ifc_create_default_route(%s, %d) = %d", name, gw, ret); 563b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return ret; 564b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt} 565b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt 566eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran// Needed by code in hidden partner repositories / branches, so don't delete. 567eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandranint ifc_enable(const char *ifname) 568eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran{ 569eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran int result; 570eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran 571eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran ifc_init(); 572eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran result = ifc_up(ifname); 573eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran ifc_close(); 574eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran return result; 575eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran} 576eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran 577e5ab3e3a4c23077ede0515320c5585a99b236671Sreeram Ramachandran// Needed by code in hidden partner repositories / branches, so don't delete. 578eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandranint ifc_disable(const char *ifname) 579eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran{ 580eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran unsigned addr, count; 581eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran int result; 582eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran 583eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran ifc_init(); 584eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran result = ifc_down(ifname); 585eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran 586eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran ifc_set_addr(ifname, 0); 587eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran for (count=0, addr=1;((addr != 0) && (count < 255)); count++) { 588eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran if (ifc_get_addr(ifname, &addr) < 0) 589eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran break; 590eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran if (addr) 591eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran ifc_set_addr(ifname, 0); 592eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran } 593eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran 594eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran ifc_close(); 595eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran return result; 596eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran} 597eec232603d314e486888e5a0d2dd8d507c266be7Sreeram Ramachandran 598979203ee34084327bf4f20ad1f878450de94826eWink Savilleint ifc_reset_connections(const char *ifname, const int reset_mask) 599dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 600dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifdef HAVE_ANDROID_OS 6016cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti int result, success; 60217622d09d5ba54ae3c8b11644c6d7556bdc6644cSreeram Ramachandran in_addr_t myaddr = 0; 603dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct ifreq ifr; 6046cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti struct in6_ifreq ifr6; 605dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 606979203ee34084327bf4f20ad1f878450de94826eWink Saville if (reset_mask & RESET_IPV4_ADDRESSES) { 607979203ee34084327bf4f20ad1f878450de94826eWink Saville /* IPv4. Clear connections on the IP address. */ 608979203ee34084327bf4f20ad1f878450de94826eWink Saville ifc_init(); 60917622d09d5ba54ae3c8b11644c6d7556bdc6644cSreeram Ramachandran if (!(reset_mask & RESET_IGNORE_INTERFACE_ADDRESS)) { 61017622d09d5ba54ae3c8b11644c6d7556bdc6644cSreeram Ramachandran ifc_get_info(ifname, &myaddr, NULL, NULL); 61117622d09d5ba54ae3c8b11644c6d7556bdc6644cSreeram Ramachandran } 612979203ee34084327bf4f20ad1f878450de94826eWink Saville ifc_init_ifr(ifname, &ifr); 613979203ee34084327bf4f20ad1f878450de94826eWink Saville init_sockaddr_in(&ifr.ifr_addr, myaddr); 614979203ee34084327bf4f20ad1f878450de94826eWink Saville result = ioctl(ifc_ctl_sock, SIOCKILLADDR, &ifr); 615979203ee34084327bf4f20ad1f878450de94826eWink Saville ifc_close(); 616979203ee34084327bf4f20ad1f878450de94826eWink Saville } else { 617979203ee34084327bf4f20ad1f878450de94826eWink Saville result = 0; 618979203ee34084327bf4f20ad1f878450de94826eWink Saville } 6197d05a80da8c210d11df657bcec8b19a6bf1e8a16Dmitry Shmidt 620979203ee34084327bf4f20ad1f878450de94826eWink Saville if (reset_mask & RESET_IPV6_ADDRESSES) { 621979203ee34084327bf4f20ad1f878450de94826eWink Saville /* 622979203ee34084327bf4f20ad1f878450de94826eWink Saville * IPv6. On Linux, when an interface goes down it loses all its IPv6 623979203ee34084327bf4f20ad1f878450de94826eWink Saville * addresses, so we don't know which connections belonged to that interface 624979203ee34084327bf4f20ad1f878450de94826eWink Saville * So we clear all unused IPv6 connections on the device by specifying an 625979203ee34084327bf4f20ad1f878450de94826eWink Saville * empty IPv6 address. 626979203ee34084327bf4f20ad1f878450de94826eWink Saville */ 627979203ee34084327bf4f20ad1f878450de94826eWink Saville ifc_init6(); 628979203ee34084327bf4f20ad1f878450de94826eWink Saville // This implicitly specifies an address of ::, i.e., kill all IPv6 sockets. 629979203ee34084327bf4f20ad1f878450de94826eWink Saville memset(&ifr6, 0, sizeof(ifr6)); 630979203ee34084327bf4f20ad1f878450de94826eWink Saville success = ioctl(ifc_ctl_sock6, SIOCKILLADDR, &ifr6); 631979203ee34084327bf4f20ad1f878450de94826eWink Saville if (result == 0) { 632979203ee34084327bf4f20ad1f878450de94826eWink Saville result = success; 633979203ee34084327bf4f20ad1f878450de94826eWink Saville } 634979203ee34084327bf4f20ad1f878450de94826eWink Saville ifc_close6(); 6356cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti } 6366cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti 637dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return result; 638dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else 639dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 640dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 641dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 642dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 643dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* 644dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Removes the default route for the named interface. 645dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 646dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_remove_default_route(const char *ifname) 647dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 648dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct rtentry rt; 649dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int result; 650dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 651dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init(); 652dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(&rt, 0, sizeof(rt)); 653dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project rt.rt_dev = (void *)ifname; 654dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project rt.rt_flags = RTF_UP|RTF_GATEWAY; 655dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project init_sockaddr_in(&rt.rt_dst, 0); 656dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if ((result = ioctl(ifc_ctl_sock, SIOCDELRT, &rt)) < 0) { 6578d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("failed to remove default route for %s: %s", ifname, strerror(errno)); 658dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 659dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_close(); 660dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return result; 661dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 662dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 663dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint 664dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectifc_configure(const char *ifname, 665dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project in_addr_t address, 66609dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt uint32_t prefixLength, 667dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project in_addr_t gateway, 668dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project in_addr_t dns1, 669dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project in_addr_t dns2) { 670dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 671dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char dns_prop_name[PROPERTY_KEY_MAX]; 672dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 673dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init(); 674dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 675dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ifc_up(ifname)) { 676dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printerr("failed to turn on interface %s: %s\n", ifname, strerror(errno)); 677dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_close(); 678dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 679dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 680dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ifc_set_addr(ifname, address)) { 681dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printerr("failed to set ipaddr %s: %s\n", ipaddr_to_string(address), strerror(errno)); 682dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_close(); 683dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 684dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 68509dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt if (ifc_set_prefixLength(ifname, prefixLength)) { 68609dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt printerr("failed to set prefixLength %d: %s\n", prefixLength, strerror(errno)); 687dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_close(); 688dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 689dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 690dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ifc_create_default_route(ifname, gateway)) { 691dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printerr("failed to set default route %s: %s\n", ipaddr_to_string(gateway), strerror(errno)); 692dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_close(); 693dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 694dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 695dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 696dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_close(); 697dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 698c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns1", ifname); 699dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project property_set(dns_prop_name, dns1 ? ipaddr_to_string(dns1) : ""); 700c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns2", ifname); 701dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project property_set(dns_prop_name, dns2 ? ipaddr_to_string(dns2) : ""); 702dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 703dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 704dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 705