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