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> 49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define LOGD printf 50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define LOGW printf 51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif 52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int ifc_ctl_sock = -1; 548984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naikstatic int ifc_ctl_sock6 = -1; 55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid printerr(char *fmt, ...); 56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 57b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt#define DBG 0 5847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti#define INET_ADDRLEN 4 5947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti#define INET6_ADDRLEN 16 60b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt 6109dd819d2794caf1a17cd03592c100755fb25577Robert Greenwaltin_addr_t prefixLengthToIpv4Netmask(int prefix_length) 6209dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt{ 6309dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt in_addr_t mask = 0; 6409dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt 6509dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt // C99 (6.5.7): shifts of 32 bits have undefined results 6609dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt if (prefix_length <= 0 || prefix_length > 32) { 6709dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt return 0; 6809dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt } 6909dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt 7009dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt mask = ~mask << (32 - prefix_length); 7109dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt mask = htonl(mask); 7209dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt 7309dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt return mask; 7409dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt} 7509dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt 7609dd819d2794caf1a17cd03592c100755fb25577Robert Greenwaltint ipv4NetmaskToPrefixLength(in_addr_t mask) 7709dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt{ 7809dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt mask = ntohl(mask); 7909dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt int prefixLength = 0; 8009dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt uint32_t m = (uint32_t)mask; 8109dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt while (m & 0x80000000) { 8209dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt prefixLength++; 8309dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt m = m << 1; 8409dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt } 8509dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt return prefixLength; 8609dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt} 8709dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt 88c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczakstatic const char *ipaddr_to_string(in_addr_t addr) 89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct in_addr in_addr; 91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project in_addr.s_addr = addr; 93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return inet_ntoa(in_addr); 94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 9647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colittiint string_to_ip(const char *string, struct sockaddr_storage *ss) { 9747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct addrinfo hints, *ai; 9847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti int ret; 9947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 10047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (ss == NULL) { 10147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return -EFAULT; 10247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 10347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 10447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti memset(&hints, 0, sizeof(hints)); 10547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti hints.ai_family = AF_UNSPEC; 10647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti hints.ai_flags = AI_NUMERICHOST; 10747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti hints.ai_socktype = SOCK_DGRAM; 10847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 10947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti ret = getaddrinfo(string, NULL, &hints, &ai); 11047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (ret == 0) { 11147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti memcpy(ss, ai->ai_addr, ai->ai_addrlen); 11247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti freeaddrinfo(ai); 11347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 11447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 11547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return ret; 11647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti} 11747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_init(void) 119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 120b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int ret; 121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ifc_ctl_sock == -1) { 122b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt ifc_ctl_sock = socket(AF_INET, SOCK_DGRAM, 0); 123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ifc_ctl_sock < 0) { 124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project printerr("socket() failed: %s\n", strerror(errno)); 125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 127b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt 128b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt ret = ifc_ctl_sock < 0 ? -1 : 0; 129b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (DBG) printerr("ifc_init_returning %d", ret); 130b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return ret; 131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1338984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naikint ifc_init6(void) 1348984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik{ 1358984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (ifc_ctl_sock6 == -1) { 1368984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik ifc_ctl_sock6 = socket(AF_INET6, SOCK_DGRAM, 0); 1378984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (ifc_ctl_sock6 < 0) { 1388984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik printerr("socket() failed: %s\n", strerror(errno)); 1398984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 1408984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 1418984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik return ifc_ctl_sock6 < 0 ? -1 : 0; 1428984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik} 1438984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid ifc_close(void) 145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 146b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (DBG) printerr("ifc_close"); 147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (ifc_ctl_sock != -1) { 148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project (void)close(ifc_ctl_sock); 149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_ctl_sock = -1; 150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 1538984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naikvoid ifc_close6(void) 1548984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik{ 1558984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (ifc_ctl_sock6 != -1) { 1568984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik (void)close(ifc_ctl_sock6); 1578984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik ifc_ctl_sock6 = -1; 1588984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 1598984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik} 1608984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void ifc_init_ifr(const char *name, struct ifreq *ifr) 162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(ifr, 0, sizeof(struct ifreq)); 164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project strncpy(ifr->ifr_name, name, IFNAMSIZ); 165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifr->ifr_name[IFNAMSIZ - 1] = 0; 166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_get_hwaddr(const char *name, void *ptr) 169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int r; 171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct ifreq ifr; 172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init_ifr(name, &ifr); 173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project r = ioctl(ifc_ctl_sock, SIOCGIFHWADDR, &ifr); 175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(r < 0) return -1; 176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 177c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak memcpy(ptr, &ifr.ifr_hwaddr.sa_data, ETH_ALEN); 178b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return 0; 179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_get_ifindex(const char *name, int *if_indexp) 182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int r; 184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct ifreq ifr; 185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init_ifr(name, &ifr); 186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project r = ioctl(ifc_ctl_sock, SIOCGIFINDEX, &ifr); 188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(r < 0) return -1; 189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *if_indexp = ifr.ifr_ifindex; 1917d05a80da8c210d11df657bcec8b19a6bf1e8a16Dmitry Shmidt return 0; 192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int ifc_set_flags(const char *name, unsigned set, unsigned clr) 195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct ifreq ifr; 197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init_ifr(name, &ifr); 198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(ioctl(ifc_ctl_sock, SIOCGIFFLAGS, &ifr) < 0) return -1; 200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifr.ifr_flags = (ifr.ifr_flags & (~clr)) | set; 201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return ioctl(ifc_ctl_sock, SIOCSIFFLAGS, &ifr); 202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_up(const char *name) 205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 206b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int ret = ifc_set_flags(name, IFF_UP, 0); 207b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (DBG) printerr("ifc_up(%s) = %d", name, ret); 208b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return ret; 209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_down(const char *name) 212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 213b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int ret = ifc_set_flags(name, 0, IFF_UP); 214b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (DBG) printerr("ifc_down(%s) = %d", name, ret); 215b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return ret; 216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void init_sockaddr_in(struct sockaddr *sa, in_addr_t addr) 219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct sockaddr_in *sin = (struct sockaddr_in *) sa; 221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sin->sin_family = AF_INET; 222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sin->sin_port = 0; 223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project sin->sin_addr.s_addr = addr; 224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_set_addr(const char *name, in_addr_t addr) 227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct ifreq ifr; 229b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int ret; 230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init_ifr(name, &ifr); 232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project init_sockaddr_in(&ifr.ifr_addr, addr); 2337d05a80da8c210d11df657bcec8b19a6bf1e8a16Dmitry Shmidt 234b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt ret = ioctl(ifc_ctl_sock, SIOCSIFADDR, &ifr); 235b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (DBG) printerr("ifc_set_addr(%s, xx) = %d", name, ret); 236b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return ret; 237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 23947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti/* 24047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * Adds or deletes an IP address on an interface. 24147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * 24247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * Action is one of: 24347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * - RTM_NEWADDR (to add a new address) 24447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * - RTM_DELADDR (to delete an existing address) 24547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * 24647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * Returns zero on success and negative errno on failure. 24747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti */ 24847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colittiint ifc_act_on_address(int action, const char *name, const char *address, 24947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti int prefixlen) { 25047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti int ifindex, s, len, ret; 25147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct sockaddr_storage ss; 25247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti void *addr; 25347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti size_t addrlen; 25447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct { 25547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct nlmsghdr n; 25647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct ifaddrmsg r; 25747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Allow for IPv6 address, headers, and padding. 25847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti char attrbuf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + 25947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti NLMSG_ALIGN(sizeof(struct rtattr)) + 26047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti NLMSG_ALIGN(INET6_ADDRLEN)]; 26147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } req; 26247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct rtattr *rta; 26347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct nlmsghdr *nh; 26447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct nlmsgerr *err; 26547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti char buf[NLMSG_ALIGN(sizeof(struct nlmsghdr)) + 26647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti NLMSG_ALIGN(sizeof(struct nlmsgerr)) + 26747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti NLMSG_ALIGN(sizeof(struct nlmsghdr))]; 26847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 26947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Get interface ID. 27047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti ifindex = if_nametoindex(name); 27147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (ifindex == 0) { 27247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return -errno; 27347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 27447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 27547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Convert string representation to sockaddr_storage. 27647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti ret = string_to_ip(address, &ss); 27747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (ret) { 27847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return ret; 27947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 28047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 28147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Determine address type and length. 28247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (ss.ss_family == AF_INET) { 28347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct sockaddr_in *sin = (struct sockaddr_in *) &ss; 28447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti addr = &sin->sin_addr; 28547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti addrlen = INET_ADDRLEN; 28647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } else if (ss.ss_family == AF_INET6) { 28747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &ss; 28847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti addr = &sin6->sin6_addr; 28947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti addrlen = INET6_ADDRLEN; 29047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } else { 29147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return -EAFNOSUPPORT; 29247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 29347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 29447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Fill in netlink structures. 29547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti memset(&req, 0, sizeof(req)); 29647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 29747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Netlink message header. 29847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.r)); 29947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti req.n.nlmsg_type = action; 30047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; 30147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti req.n.nlmsg_pid = getpid(); 30247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 30347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Interface address message header. 30447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti req.r.ifa_family = ss.ss_family; 30547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti req.r.ifa_prefixlen = prefixlen; 30647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti req.r.ifa_index = ifindex; 30747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 30847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Routing attribute. Contains the actual IP address. 30947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti rta = (struct rtattr *) (((char *) &req) + NLMSG_ALIGN(req.n.nlmsg_len)); 31047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti rta->rta_type = IFA_LOCAL; 31147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti rta->rta_len = RTA_LENGTH(addrlen); 31247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti req.n.nlmsg_len = NLMSG_ALIGN(req.n.nlmsg_len) + RTA_LENGTH(addrlen); 31347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti memcpy(RTA_DATA(rta), addr, addrlen); 31447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 31547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); 31647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (send(s, &req, req.n.nlmsg_len, 0) < 0) { 31747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti close(s); 31847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return -errno; 31947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 32047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 32147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti len = recv(s, buf, sizeof(buf), 0); 32247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti close(s); 32347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (len < 0) { 32447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return -errno; 32547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 32647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 32747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Parse the acknowledgement to find the return code. 32847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti nh = (struct nlmsghdr *) buf; 32947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (!NLMSG_OK(nh, (unsigned) len) || nh->nlmsg_type != NLMSG_ERROR) { 33047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return -EINVAL; 33147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 33247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti err = NLMSG_DATA(nh); 33347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 33447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Return code is negative errno. 33547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return err->error; 33647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti} 33747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 33847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colittiint ifc_add_address(const char *name, const char *address, int prefixlen) { 33947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return ifc_act_on_address(RTM_NEWADDR, name, address, prefixlen); 34047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti} 34147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 34247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colittiint ifc_del_address(const char *name, const char * address, int prefixlen) { 34347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return ifc_act_on_address(RTM_DELADDR, name, address, prefixlen); 34447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti} 34547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 34647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti/* 34747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * Clears IPv6 addresses on the specified interface. 34847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti */ 34947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colittiint ifc_clear_ipv6_addresses(const char *name) { 35047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti char rawaddrstr[INET6_ADDRSTRLEN], addrstr[INET6_ADDRSTRLEN]; 35147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti unsigned int prefixlen; 35247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti int lasterror = 0, i, j, ret; 35347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti char ifname[64]; // Currently, IFNAMSIZ = 16. 35447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti FILE *f = fopen("/proc/net/if_inet6", "r"); 35547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (!f) { 35647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return -errno; 35747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 35847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 35947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Format: 36047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // 20010db8000a0001fc446aa4b5b347ed 03 40 00 01 wlan0 36147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti while (fscanf(f, "%32s %*02x %02x %*02x %*02x %63s\n", 36247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti rawaddrstr, &prefixlen, ifname) == 3) { 36347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Is this the interface we're looking for? 36447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (strcmp(name, ifname)) { 36547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti continue; 36647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 36747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 36847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Put the colons back into the address. 36947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti for (i = 0, j = 0; i < 32; i++, j++) { 37047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti addrstr[j] = rawaddrstr[i]; 37147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (i % 4 == 3) { 37247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti addrstr[++j] = ':'; 37347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 37447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 37547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti addrstr[j - 1] = '\0'; 37647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 37747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // Don't delete the link-local address as well, or it will disable IPv6 37847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti // on the interface. 37947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (strncmp(addrstr, "fe80:", 5) == 0) { 38047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti continue; 38147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 38247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 38347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti ret = ifc_del_address(ifname, addrstr, prefixlen); 38447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (ret) { 38547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti LOGE("Deleting address %s/%d on %s: %s", addrstr, prefixlen, ifname, 38647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti strerror(-ret)); 38747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti lasterror = ret; 38847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 38947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 39047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 39147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti fclose(f); 39247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return lasterror; 39347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti} 39447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 39547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti/* 39647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * Clears IPv4 addresses on the specified interface. 39747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti */ 39847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colittivoid ifc_clear_ipv4_addresses(const char *name) { 39947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti unsigned count, addr; 40047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti ifc_init(); 40147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti for (count=0, addr=1;((addr != 0) && (count < 255)); count++) { 40247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (ifc_get_addr(name, &addr) < 0) 40347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti break; 40447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti if (addr) 40547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti ifc_set_addr(name, 0); 40647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti } 40747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti ifc_close(); 40847ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti} 40947ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 41047ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti/* 41147ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti * Clears all IP addresses on the specified interface. 41247ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti */ 41347ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colittiint ifc_clear_addresses(const char *name) { 41447ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti ifc_clear_ipv4_addresses(name); 41547ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti return ifc_clear_ipv6_addresses(name); 41647ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti} 41747ddb515b7d59b29d83628c1b4e48642dc0e49baLorenzo Colitti 418c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczakint ifc_set_hwaddr(const char *name, const void *ptr) 419c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak{ 420c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak int r; 421c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak struct ifreq ifr; 422c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak ifc_init_ifr(name, &ifr); 423c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak 424c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER; 425c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak memcpy(&ifr.ifr_hwaddr.sa_data, ptr, ETH_ALEN); 426c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak return ioctl(ifc_ctl_sock, SIOCSIFHWADDR, &ifr); 427c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak} 428c88e09cb98fb3690c3cf49f5a825532e0d9bf300Szymon Jakubczak 4296f49d5f266dffee103a3af07a7f6266f405d2924Jake Hambyint ifc_set_mask(const char *name, in_addr_t mask) 4306f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby{ 4316f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby struct ifreq ifr; 432b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int ret; 4336f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby 4346f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby ifc_init_ifr(name, &ifr); 4356f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby init_sockaddr_in(&ifr.ifr_addr, mask); 4366f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby 437b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt ret = ioctl(ifc_ctl_sock, SIOCSIFNETMASK, &ifr); 438b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (DBG) printerr("ifc_set_mask(%s, xx) = %d", name, ret); 439b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return ret; 4406f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby} 4416f49d5f266dffee103a3af07a7f6266f405d2924Jake Hamby 44209dd819d2794caf1a17cd03592c100755fb25577Robert Greenwaltint ifc_set_prefixLength(const char *name, int prefixLength) 443dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 444dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct ifreq ifr; 44509dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt // TODO - support ipv6 44609dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt if (prefixLength > 32 || prefixLength < 0) return -1; 447dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 44809dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt in_addr_t mask = prefixLengthToIpv4Netmask(prefixLength); 449dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init_ifr(name, &ifr); 450dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project init_sockaddr_in(&ifr.ifr_addr, mask); 4517d05a80da8c210d11df657bcec8b19a6bf1e8a16Dmitry Shmidt 452dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return ioctl(ifc_ctl_sock, SIOCSIFNETMASK, &ifr); 453dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 454dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 4559092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidtint ifc_get_addr(const char *name, in_addr_t *addr) 4569092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt{ 4579092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt struct ifreq ifr; 4589092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt int ret = 0; 4599092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt 4609092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt ifc_init_ifr(name, &ifr); 4619092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt if (addr != NULL) { 4629092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt ret = ioctl(ifc_ctl_sock, SIOCGIFADDR, &ifr); 4639092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt if (ret < 0) { 4649092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt *addr = 0; 4659092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt } else { 4669092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt *addr = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr; 4679092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt } 4689092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt } 4699092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt return ret; 4709092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt} 4719092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt 47209dd819d2794caf1a17cd03592c100755fb25577Robert Greenwaltint ifc_get_info(const char *name, in_addr_t *addr, int *prefixLength, unsigned *flags) 473dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 474dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct ifreq ifr; 475dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init_ifr(name, &ifr); 476dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 477dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (addr != NULL) { 478dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(ioctl(ifc_ctl_sock, SIOCGIFADDR, &ifr) < 0) { 479dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *addr = 0; 480dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 481dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *addr = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr; 482dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 483dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 4847d05a80da8c210d11df657bcec8b19a6bf1e8a16Dmitry Shmidt 48509dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt if (prefixLength != NULL) { 486dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(ioctl(ifc_ctl_sock, SIOCGIFNETMASK, &ifr) < 0) { 48709dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt *prefixLength = 0; 488dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 48909dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt *prefixLength = ipv4NetmaskToPrefixLength((int) 49009dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr); 491dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 492dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 493dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 494dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if (flags != NULL) { 495dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project if(ioctl(ifc_ctl_sock, SIOCGIFFLAGS, &ifr) < 0) { 496dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *flags = 0; 497dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } else { 498dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *flags = ifr.ifr_flags; 499dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 500dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 501dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 502dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return 0; 503dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 504dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 505021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwaltint ifc_act_on_ipv4_route(int action, const char *ifname, struct in_addr dst, int prefix_length, 5068984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik struct in_addr gw) 507dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 508dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project struct rtentry rt; 509dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int result; 5108984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik in_addr_t netmask; 511dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 512dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project memset(&rt, 0, sizeof(rt)); 5138984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 514dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project rt.rt_dst.sa_family = AF_INET; 5158984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik rt.rt_dev = (void*) ifname; 5168984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 51709dd819d2794caf1a17cd03592c100755fb25577Robert Greenwalt netmask = prefixLengthToIpv4Netmask(prefix_length); 5188984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik init_sockaddr_in(&rt.rt_genmask, netmask); 5198984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik init_sockaddr_in(&rt.rt_dst, dst.s_addr); 5208984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik rt.rt_flags = RTF_UP; 5218984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 5228984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (prefix_length == 32) { 5238984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik rt.rt_flags |= RTF_HOST; 5248984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 5258984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 5268984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (gw.s_addr != 0) { 5278984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik rt.rt_flags |= RTF_GATEWAY; 5288984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik init_sockaddr_in(&rt.rt_gateway, gw.s_addr); 5298984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 5308984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 531dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init(); 5328984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 5338984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (ifc_ctl_sock < 0) { 5348984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik return -errno; 5358984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 5368984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 537021d0a2e7cd7c65036d425b7bef775bbc1733864Robert Greenwalt result = ioctl(ifc_ctl_sock, action, &rt); 5388984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (result < 0) { 5398984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik if (errno == EEXIST) { 5408984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik result = 0; 5418984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } else { 5428984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik result = -errno; 5438984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik } 544dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project } 545dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_close(); 546dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return result; 547dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 548dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 549b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt/* deprecated - v4 only */ 5508984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naikint ifc_create_default_route(const char *name, in_addr_t gw) 5518984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik{ 5528984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik struct in_addr in_dst, in_gw; 5538984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 5548984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik in_dst.s_addr = 0; 5558984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik in_gw.s_addr = gw; 5568984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 557b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt int ret = ifc_act_on_ipv4_route(SIOCADDRT, name, in_dst, 0, in_gw); 558b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt if (DBG) printerr("ifc_create_default_route(%s, %d) = %d", name, gw, ret); 559b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return ret; 560b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt} 561b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt 562b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt/* deprecated v4-only */ 563b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwaltint ifc_add_host_route(const char *name, in_addr_t dst) 564b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt{ 565b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt struct in_addr in_dst, in_gw; 566b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt 567b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt in_dst.s_addr = dst; 568b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt in_gw.s_addr = 0; 569b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt 570b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt return ifc_act_on_ipv4_route(SIOCADDRT, name, in_dst, 32, in_gw); 5718984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik} 5728984bb9691f8d3e2665f7aae0896b9bd2ade0c19Banavathu, Srinivas Naik 573feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwoodint ifc_enable(const char *ifname) 574feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood{ 575feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood int result; 576feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood 577feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood ifc_init(); 578feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood result = ifc_up(ifname); 579feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood ifc_close(); 580feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood return result; 581feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood} 582feb63e9e6f2d7aed5f0f21347992218ed8acb9f4Mike Lockwood 583dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint ifc_disable(const char *ifname) 584dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{ 5859092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt unsigned addr, count; 586dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project int result; 587dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 588dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_init(); 589dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project result = ifc_down(ifname); 5909092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt 591dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_set_addr(ifname, 0); 5929092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt for (count=0, addr=1;((addr != 0) && (count < 255)); count++) { 5939092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt if (ifc_get_addr(ifname, &addr) < 0) 5949092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt break; 5959092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt if (addr) 5969092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt ifc_set_addr(ifname, 0); 5979092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt } 5989092b91ccaa4c6069036f72163e6473a5ca408c4Dmitry Shmidt 599dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project ifc_close(); 600dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project return result; 601dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} 602dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project 603979203ee34084327bf4f20ad1f878450de94826eWink Saville#define RESET_IPV4_ADDRESSES 0x01 604979203ee34084327bf4f20ad1f878450de94826eWink Saville#define RESET_IPV6_ADDRESSES 0x02 605979203ee34084327bf4f20ad1f878450de94826eWink Saville#define RESET_ALL_ADDRESSES (RESET_IPV4_ADDRESSES | RESET_IPV6_ADDRESSES) 606979203ee34084327bf4f20ad1f878450de94826eWink Saville 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) { 689dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOGD("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) { 755b6b48ae47a44cb231d0a16ca618ac28b0024c11cRobert Greenwalt LOGD("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) { 776dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project LOGD("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