194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood/* 294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * Copyright (C) 2011 The Android Open Source Project 394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * 494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * Licensed under the Apache License, Version 2.0 (the "License"); 594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * you may not use this file except in compliance with the License. 694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * You may obtain a copy of the License at 794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * 894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * http://www.apache.org/licenses/LICENSE-2.0 994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * 1094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * Unless required by applicable law or agreed to in writing, software 1194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * distributed under the License is distributed on an "AS IS" BASIS, 1294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * See the License for the specific language governing permissions and 1494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * limitations under the License. 1594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood */ 1694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 1794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include <stdio.h> 1894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include <stdlib.h> 1994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include <string.h> 2094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include <errno.h> 2194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 2294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include <arpa/inet.h> 2394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include <netinet/in.h> 2494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include <sys/stat.h> 2594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include <sys/types.h> 2694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include <sys/socket.h> 2794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include <sys/ioctl.h> 2894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include <linux/if.h> 2994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include <linux/route.h> 3094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 3194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#define LOG_TAG "ip-up-vpn" 3294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#include <cutils/log.h> 3394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 3494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood#define DIR "/data/misc/vpn/" 3594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 3694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodstatic const char *env(const char *name) { 3794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood const char *value = getenv(name); 3894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return value ? value : ""; 3994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} 4094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 4194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodstatic int set_address(struct sockaddr *sa, const char *address) { 4294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood sa->sa_family = AF_INET; 4394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood errno = EINVAL; 4494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return inet_pton(AF_INET, address, &((struct sockaddr_in *)sa)->sin_addr); 4594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} 4694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 4794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood/* 4894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * The primary goal is to create a file with VPN parameters. Currently they 49a9e8374c72bf39c55bfe42d917a0c4be03a14a33Lorenzo Colitti * are interface, addresses, routes, DNS servers, and search domains and VPN 50a9e8374c72bf39c55bfe42d917a0c4be03a14a33Lorenzo Colitti * server address. Each parameter occupies one line in the file, and it can be 51a9e8374c72bf39c55bfe42d917a0c4be03a14a33Lorenzo Colitti * an empty string or space-separated values. The order and the format must be 52a9e8374c72bf39c55bfe42d917a0c4be03a14a33Lorenzo Colitti * consistent with com.android.server.connectivity.Vpn. Here is an example. 5394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * 5494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * ppp0 5594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * 192.168.1.100/24 5694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * 0.0.0.0/0 5794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * 192.168.1.1 192.168.1.2 5894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * example.org 59a9e8374c72bf39c55bfe42d917a0c4be03a14a33Lorenzo Colitti * 192.0.2.1 6094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * 6194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * The secondary goal is to unify the outcome of VPN. The current baseline 6294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * is to have an interface configured with the given address and netmask 6394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * and maybe add a host route to protect the tunnel. PPP-based VPN already 6494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * does this, but others might not. Routes, DNS servers, and search domains 6594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood * are handled by the framework since they can be overridden by the users. 6694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood */ 6794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwoodint main(int argc, char **argv) 6894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood{ 6994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood FILE *state = fopen(DIR ".tmp", "wb"); 7094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (!state) { 7194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGE("Cannot create state: %s", strerror(errno)); 7294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return 1; 7394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 7494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 7594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (argc >= 6) { 7694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood /* Invoked by pppd. */ 7794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood fprintf(state, "%s\n", argv[1]); 7894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood fprintf(state, "%s/32\n", argv[4]); 7994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood fprintf(state, "0.0.0.0/0\n"); 8094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood fprintf(state, "%s %s\n", env("DNS1"), env("DNS2")); 8194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood fprintf(state, "\n"); 82a9e8374c72bf39c55bfe42d917a0c4be03a14a33Lorenzo Colitti fprintf(state, "\n"); 8394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } else if (argc == 2) { 8494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood /* Invoked by racoon. */ 8594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood const char *interface = env("INTERFACE"); 8694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood const char *address = env("INTERNAL_ADDR4"); 8794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood const char *routes = env("SPLIT_INCLUDE_CIDR"); 8894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 8994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood int s = socket(AF_INET, SOCK_DGRAM, 0); 9094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood struct ifreq ifr; 9194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood memset(&ifr, 0, sizeof(ifr)); 9294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 9394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood /* Bring up the interface. */ 9494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ifr.ifr_flags = IFF_UP; 9594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood strncpy(ifr.ifr_name, interface, IFNAMSIZ); 9694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (ioctl(s, SIOCSIFFLAGS, &ifr)) { 9794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGE("Cannot bring up %s: %s", interface, strerror(errno)); 9894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return 1; 9994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 10094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 10194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood /* Set the address. */ 10294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (!set_address(&ifr.ifr_addr, address) || 10394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ioctl(s, SIOCSIFADDR, &ifr)) { 10494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGE("Cannot set address: %s", strerror(errno)); 10594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return 1; 10694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 10794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 10894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood /* Set the netmask. */ 10994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (set_address(&ifr.ifr_netmask, env("INTERNAL_NETMASK4"))) { 11094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (ioctl(s, SIOCSIFNETMASK, &ifr)) { 11194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGE("Cannot set netmask: %s", strerror(errno)); 11294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return 1; 11394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 11494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 11594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 11694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood /* TODO: Send few packets to trigger phase 2? */ 11794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 11894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood fprintf(state, "%s\n", interface); 11994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood fprintf(state, "%s/%s\n", address, env("INTERNAL_CIDR4")); 12094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood fprintf(state, "%s\n", routes[0] ? routes : "0.0.0.0/0"); 12194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood fprintf(state, "%s\n", env("INTERNAL_DNS4_LIST")); 12294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood fprintf(state, "%s\n", env("DEFAULT_DOMAIN")); 123a9e8374c72bf39c55bfe42d917a0c4be03a14a33Lorenzo Colitti fprintf(state, "%s\n", env("REMOTE_ADDR")); 12494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } else { 12594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGE("Cannot parse parameters"); 12694afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return 1; 12794afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 12894afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood 12994afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood fclose(state); 13094afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood if (chmod(DIR ".tmp", 0444) || rename(DIR ".tmp", DIR "state")) { 13194afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood ALOGE("Cannot write state: %s", strerror(errno)); 13294afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return 1; 13394afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood } 13494afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood return 0; 13594afecf4b6f437b3ee9a076242402e421c6c07a6Mike Lockwood} 136