ifc_utils.c revision 2d640c2640b957f704d86fcaea6e5a4af54dde2c
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 566b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt/* deprecated v4-only */ 567b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwaltint ifc_add_host_route(const char *name, in_addr_t dst) 568b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt{ 569b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt struct in_addr in_dst, in_gw; 570b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt 571b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt in_dst.s_addr = dst; 572b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt in_gw.s_addr = 0; 573b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt 574b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return ifc_act_on_ipv4_route(SIOCADDRT, name, in_dst, 32, in_gw); 5758984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik} 5768984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 577feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwoodint ifc_enable(const char *ifname) 578feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood{ 579feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood int result; 580feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood 581feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood ifc_init(); 582feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood result = ifc_up(ifname); 583feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood ifc_close(); 584feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood return result; 585feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood} 586feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood 587dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_disable(const char *ifname) 588dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 5899092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt unsigned addr, count; 590dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int result; 591dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 592dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init(); 593dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project result = ifc_down(ifname); 5949092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt 595dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_set_addr(ifname, 0); 5969092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt for (count=0, addr=1;((addr != 0) && (count < 255)); count++) { 5979092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt if (ifc_get_addr(ifname, &addr) < 0) 5989092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt break; 5999092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt if (addr) 6009092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt ifc_set_addr(ifname, 0); 6019092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt } 6029092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt 603dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_close(); 604dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return result; 605dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 606dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 607979203ee34084327bf4f20ad1f878450de94826eWink Savilleint ifc_reset_connections(const char *ifname, const int reset_mask) 608dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 609dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifdef HAVE_ANDROID_OS 6106cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti int result, success; 611dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project in_addr_t myaddr; 612dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct ifreq ifr; 6136cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti struct in6_ifreq ifr6; 614dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 615979203ee34084327bf4f20ad1f878450de94826eWink Saville if (reset_mask & RESET_IPV4_ADDRESSES) { 616979203ee34084327bf4f20ad1f878450de94826eWink Saville /* IPv4. Clear connections on the IP address. */ 617979203ee34084327bf4f20ad1f878450de94826eWink Saville ifc_init(); 618979203ee34084327bf4f20ad1f878450de94826eWink Saville ifc_get_info(ifname, &myaddr, NULL, NULL); 619979203ee34084327bf4f20ad1f878450de94826eWink Saville ifc_init_ifr(ifname, &ifr); 620979203ee34084327bf4f20ad1f878450de94826eWink Saville init_sockaddr_in(&ifr.ifr_addr, myaddr); 621979203ee34084327bf4f20ad1f878450de94826eWink Saville result = ioctl(ifc_ctl_sock, SIOCKILLADDR, &ifr); 622979203ee34084327bf4f20ad1f878450de94826eWink Saville ifc_close(); 623979203ee34084327bf4f20ad1f878450de94826eWink Saville } else { 624979203ee34084327bf4f20ad1f878450de94826eWink Saville result = 0; 625979203ee34084327bf4f20ad1f878450de94826eWink Saville } 6267d05a80da8c210d11df657bcec8b19a6bf1e8a16Dmitry Shmidt 627979203ee34084327bf4f20ad1f878450de94826eWink Saville if (reset_mask & RESET_IPV6_ADDRESSES) { 628979203ee34084327bf4f20ad1f878450de94826eWink Saville /* 629979203ee34084327bf4f20ad1f878450de94826eWink Saville * IPv6. On Linux, when an interface goes down it loses all its IPv6 630979203ee34084327bf4f20ad1f878450de94826eWink Saville * addresses, so we don't know which connections belonged to that interface 631979203ee34084327bf4f20ad1f878450de94826eWink Saville * So we clear all unused IPv6 connections on the device by specifying an 632979203ee34084327bf4f20ad1f878450de94826eWink Saville * empty IPv6 address. 633979203ee34084327bf4f20ad1f878450de94826eWink Saville */ 634979203ee34084327bf4f20ad1f878450de94826eWink Saville ifc_init6(); 635979203ee34084327bf4f20ad1f878450de94826eWink Saville // This implicitly specifies an address of ::, i.e., kill all IPv6 sockets. 636979203ee34084327bf4f20ad1f878450de94826eWink Saville memset(&ifr6, 0, sizeof(ifr6)); 637979203ee34084327bf4f20ad1f878450de94826eWink Saville success = ioctl(ifc_ctl_sock6, SIOCKILLADDR, &ifr6); 638979203ee34084327bf4f20ad1f878450de94826eWink Saville if (result == 0) { 639979203ee34084327bf4f20ad1f878450de94826eWink Saville result = success; 640979203ee34084327bf4f20ad1f878450de94826eWink Saville } 641979203ee34084327bf4f20ad1f878450de94826eWink Saville ifc_close6(); 6426cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti } 6436cf73eadc752b619bc7c38d0d1277891eccbf81dLorenzo Colitti 644dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return result; 645dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else 646dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 647dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 648dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 649dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 650dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* 651dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Remove the routes associated with the named interface. 652dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 653dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_remove_host_routes(const char *name) 654dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 655dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char ifname[64]; 656dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project in_addr_t dest, gway, mask; 657dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int flags, refcnt, use, metric, mtu, win, irtt; 658dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct rtentry rt; 659dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project FILE *fp; 660dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct in_addr addr; 661dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 662dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fp = fopen("/proc/net/route", "r"); 663dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (fp == NULL) 664dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 665dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project /* Skip the header line */ 666dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (fscanf(fp, "%*[^\n]\n") < 0) { 667dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fclose(fp); 668dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 669dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 670dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init(); 671dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project for (;;) { 672dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int nread = fscanf(fp, "%63s%X%X%X%d%d%d%X%d%d%d\n", 673dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifname, &dest, &gway, &flags, &refcnt, &use, &metric, &mask, 674dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project &mtu, &win, &irtt); 675dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (nread != 11) { 676dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project break; 677dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 678dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if ((flags & (RTF_UP|RTF_HOST)) != (RTF_UP|RTF_HOST) 679dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project || strcmp(ifname, name) != 0) { 680dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project continue; 681dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 682dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(&rt, 0, sizeof(rt)); 683dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project rt.rt_dev = (void *)name; 684dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project init_sockaddr_in(&rt.rt_dst, dest); 685dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project init_sockaddr_in(&rt.rt_gateway, gway); 686dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project init_sockaddr_in(&rt.rt_genmask, mask); 687dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project addr.s_addr = dest; 688dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ioctl(ifc_ctl_sock, SIOCDELRT, &rt) < 0) { 6898d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("failed to remove route for %s to %s: %s", 690dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifname, inet_ntoa(addr), strerror(errno)); 691dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 692dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 693dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project fclose(fp); 694dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_close(); 695dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 696dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 697dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 698dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* 699b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt * Return the address of the default gateway 700b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt * 701b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt * TODO: factor out common code from this and remove_host_routes() 702b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt * so that we only scan /proc/net/route in one place. 703b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt * 704b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt * DEPRECATED 705b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt */ 706b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwaltint ifc_get_default_route(const char *ifname) 707b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt{ 708b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt char name[64]; 709b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt in_addr_t dest, gway, mask; 710b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int flags, refcnt, use, metric, mtu, win, irtt; 711b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int result; 712b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt FILE *fp; 713b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt 714b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt fp = fopen("/proc/net/route", "r"); 715b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (fp == NULL) 716b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return 0; 717b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt /* Skip the header line */ 718b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (fscanf(fp, "%*[^\n]\n") < 0) { 719b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt fclose(fp); 720b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return 0; 721b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt } 722b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt ifc_init(); 723b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt result = 0; 724b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt for (;;) { 725b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int nread = fscanf(fp, "%63s%X%X%X%d%d%d%X%d%d%d\n", 726b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt name, &dest, &gway, &flags, &refcnt, &use, &metric, &mask, 727b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt &mtu, &win, &irtt); 728b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (nread != 11) { 729b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt break; 730b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt } 731b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if ((flags & (RTF_UP|RTF_GATEWAY)) == (RTF_UP|RTF_GATEWAY) 732b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt && dest == 0 733b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt && strcmp(ifname, name) == 0) { 734b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt result = gway; 735b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt break; 736b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt } 737b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt } 738b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt fclose(fp); 739b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt ifc_close(); 740b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return result; 741b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt} 742b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt 743b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt/* 744b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt * Sets the specified gateway as the default route for the named interface. 745b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt * DEPRECATED 746b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt */ 747b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwaltint ifc_set_default_route(const char *ifname, in_addr_t gateway) 748b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt{ 749b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt struct in_addr addr; 750b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int result; 751b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt 752b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt ifc_init(); 753b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt addr.s_addr = gateway; 754b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if ((result = ifc_create_default_route(ifname, gateway)) < 0) { 7558d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("failed to add %s as default route for %s: %s", 756b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt inet_ntoa(addr), ifname, strerror(errno)); 757b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt } 758b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt ifc_close(); 759b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return result; 760b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt} 761b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt 762b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt/* 763dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Removes the default route for the named interface. 764dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */ 765dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_remove_default_route(const char *ifname) 766dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 767dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct rtentry rt; 768dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int result; 769dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 770dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init(); 771dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(&rt, 0, sizeof(rt)); 772dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project rt.rt_dev = (void *)ifname; 773dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project rt.rt_flags = RTF_UP|RTF_GATEWAY; 774dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project init_sockaddr_in(&rt.rt_dst, 0); 775dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if ((result = ioctl(ifc_ctl_sock, SIOCDELRT, &rt)) < 0) { 7768d66c49258ac4f59bd67c23c9c914cca81f85b01Steve Block ALOGD("failed to remove default route for %s: %s", ifname, strerror(errno)); 777dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 778dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_close(); 779dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return result; 780dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 781dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 782dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint 783dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectifc_configure(const char *ifname, 784dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project in_addr_t address, 78509dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt uint32_t prefixLength, 786dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project in_addr_t gateway, 787dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project in_addr_t dns1, 788dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project in_addr_t dns2) { 789dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 790dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project char dns_prop_name[PROPERTY_KEY_MAX]; 791dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 792dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init(); 793dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 794dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ifc_up(ifname)) { 795dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printerr("failed to turn on interface %s: %s\n", ifname, strerror(errno)); 796dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_close(); 797dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 798dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 799dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ifc_set_addr(ifname, address)) { 800dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printerr("failed to set ipaddr %s: %s\n", ipaddr_to_string(address), strerror(errno)); 801dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_close(); 802dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 803dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 80409dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt if (ifc_set_prefixLength(ifname, prefixLength)) { 80509dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt printerr("failed to set prefixLength %d: %s\n", prefixLength, strerror(errno)); 806dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_close(); 807dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 808dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 809dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ifc_create_default_route(ifname, gateway)) { 810dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printerr("failed to set default route %s: %s\n", ipaddr_to_string(gateway), strerror(errno)); 811dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_close(); 812dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return -1; 813dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 814dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 815dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_close(); 816dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 817c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns1", ifname); 818dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project property_set(dns_prop_name, dns1 ? ipaddr_to_string(dns1) : ""); 819c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns2", ifname); 820dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project property_set(dns_prop_name, dns2 ? ipaddr_to_string(dns2) : ""); 821dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 822dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 823dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 8248984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 825021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwaltint ifc_act_on_ipv6_route(int action, const char *ifname, struct in6_addr dst, int prefix_length, 8268984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik struct in6_addr gw) 8278984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik{ 8288984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik struct in6_rtmsg rtmsg; 8298984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik int result; 8308984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik int ifindex; 8318984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 8328984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik memset(&rtmsg, 0, sizeof(rtmsg)); 8338984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 8348984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik ifindex = if_nametoindex(ifname); 8358984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (ifindex == 0) { 8368984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik printerr("if_nametoindex() failed: interface %s\n", ifname); 8378984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik return -ENXIO; 8388984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 8398984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 8408984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik rtmsg.rtmsg_ifindex = ifindex; 8418984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik rtmsg.rtmsg_dst = dst; 8428984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik rtmsg.rtmsg_dst_len = prefix_length; 8438984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik rtmsg.rtmsg_flags = RTF_UP; 8448984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 8458984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (prefix_length == 128) { 8468984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik rtmsg.rtmsg_flags |= RTF_HOST; 8478984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 8488984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 8498984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (memcmp(&gw, &in6addr_any, sizeof(in6addr_any))) { 8508984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik rtmsg.rtmsg_flags |= RTF_GATEWAY; 8518984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik rtmsg.rtmsg_gateway = gw; 8528984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 8538984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 8548984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik ifc_init6(); 8558984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 8568984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (ifc_ctl_sock6 < 0) { 8578984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik return -errno; 8588984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 8598984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 860021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt result = ioctl(ifc_ctl_sock6, action, &rtmsg); 8618984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (result < 0) { 8628984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (errno == EEXIST) { 8638984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik result = 0; 8648984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } else { 8658984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik result = -errno; 8668984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 8678984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 8688984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik ifc_close6(); 8698984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik return result; 8708984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik} 8718984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 872021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwaltint ifc_act_on_route(int action, const char *ifname, const char *dst, int prefix_length, 873021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt const char *gw) 8748984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik{ 8758984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik int ret = 0; 8768984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik struct sockaddr_in ipv4_dst, ipv4_gw; 8778984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik struct sockaddr_in6 ipv6_dst, ipv6_gw; 8788984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik struct addrinfo hints, *addr_ai, *gw_ai; 8798984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 8808984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik memset(&hints, 0, sizeof(hints)); 8818984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ 8828984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik hints.ai_flags = AI_NUMERICHOST; 8838984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 8848984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik ret = getaddrinfo(dst, NULL, &hints, &addr_ai); 8858984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 8868984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (ret != 0) { 8878984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik printerr("getaddrinfo failed: invalid address %s\n", dst); 8888984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik return -EINVAL; 8898984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 8908984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 891021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt if (gw == NULL || (strlen(gw) == 0)) { 8928984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (addr_ai->ai_family == AF_INET6) { 8938984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik gw = "::"; 8948984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } else if (addr_ai->ai_family == AF_INET) { 8958984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik gw = "0.0.0.0"; 8968984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 8978984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 8988984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 899021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt if (((addr_ai->ai_family == AF_INET6) && (prefix_length < 0 || prefix_length > 128)) || 900021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt ((addr_ai->ai_family == AF_INET) && (prefix_length < 0 || prefix_length > 32))) { 901021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt printerr("ifc_add_route: invalid prefix length"); 902021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt freeaddrinfo(addr_ai); 903021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt return -EINVAL; 904021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt } 905021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt 9068984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik ret = getaddrinfo(gw, NULL, &hints, &gw_ai); 9078984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (ret != 0) { 9088984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik printerr("getaddrinfo failed: invalid gateway %s\n", gw); 9098984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik freeaddrinfo(addr_ai); 9108984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik return -EINVAL; 9118984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 9128984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 9138984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (addr_ai->ai_family != gw_ai->ai_family) { 9148984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik printerr("ifc_add_route: different address families: %s and %s\n", dst, gw); 9158984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik freeaddrinfo(addr_ai); 9168984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik freeaddrinfo(gw_ai); 9178984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik return -EINVAL; 9188984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 9198984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 9208984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (addr_ai->ai_family == AF_INET6) { 9218984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik memcpy(&ipv6_dst, addr_ai->ai_addr, sizeof(struct sockaddr_in6)); 9228984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik memcpy(&ipv6_gw, gw_ai->ai_addr, sizeof(struct sockaddr_in6)); 923021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt ret = ifc_act_on_ipv6_route(action, ifname, ipv6_dst.sin6_addr, 924021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt prefix_length, ipv6_gw.sin6_addr); 9258984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } else if (addr_ai->ai_family == AF_INET) { 9268984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik memcpy(&ipv4_dst, addr_ai->ai_addr, sizeof(struct sockaddr_in)); 9278984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik memcpy(&ipv4_gw, gw_ai->ai_addr, sizeof(struct sockaddr_in)); 928021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt ret = ifc_act_on_ipv4_route(action, ifname, ipv4_dst.sin_addr, 929021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt prefix_length, ipv4_gw.sin_addr); 9308984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } else { 9318984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik printerr("ifc_add_route: getaddrinfo returned un supported address family %d\n", 9328984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik addr_ai->ai_family); 9338984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik ret = -EAFNOSUPPORT; 9348984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 9358984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 9368984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik freeaddrinfo(addr_ai); 9378984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik freeaddrinfo(gw_ai); 9388984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik return ret; 9398984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik} 940021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt 941b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt/* 942b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt * DEPRECATED 943b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt */ 944b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwaltint ifc_add_ipv4_route(const char *ifname, struct in_addr dst, int prefix_length, 945b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt struct in_addr gw) 946b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt{ 947b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int i =ifc_act_on_ipv4_route(SIOCADDRT, ifname, dst, prefix_length, gw); 9480c613613d757c544d6ec7e5678f49a631a99d72aWink Saville if (DBG) printerr("ifc_add_ipv4_route(%s, xx, %d, xx) = %d", ifname, prefix_length, i); 949b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return i; 950b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt} 951b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt 952b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt/* 953b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt * DEPRECATED 954b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt */ 955b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwaltint ifc_add_ipv6_route(const char *ifname, struct in6_addr dst, int prefix_length, 956b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt struct in6_addr gw) 957b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt{ 958b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return ifc_act_on_ipv6_route(SIOCADDRT, ifname, dst, prefix_length, gw); 959b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt} 960b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt 961021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwaltint ifc_add_route(const char *ifname, const char *dst, int prefix_length, const char *gw) 962021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt{ 963b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int i = ifc_act_on_route(SIOCADDRT, ifname, dst, prefix_length, gw); 9640c613613d757c544d6ec7e5678f49a631a99d72aWink Saville if (DBG) printerr("ifc_add_route(%s, %s, %d, %s) = %d", ifname, dst, prefix_length, gw, i); 965b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return i; 966021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt} 967021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt 968021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwaltint ifc_remove_route(const char *ifname, const char*dst, int prefix_length, const char *gw) 969021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt{ 970021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt return ifc_act_on_route(SIOCDELRT, ifname, dst, prefix_length, gw); 971021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt} 972