You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
244 lines
6.0 KiB
244 lines
6.0 KiB
/*
|
|
* Copyright (C) 2011 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdarg.h>
|
|
#include <signal.h>
|
|
#include <poll.h>
|
|
#include <unistd.h>
|
|
|
|
#include "config.h"
|
|
#include "gcmalloc.h"
|
|
#include "schedule.h"
|
|
#include "plog.h"
|
|
|
|
#ifdef ANDROID_CHANGES
|
|
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
#include <linux/if.h>
|
|
#include <linux/if_tun.h>
|
|
|
|
#include <android/log.h>
|
|
#include <cutils/sockets.h>
|
|
#include <private/android_filesystem_config.h>
|
|
|
|
static void notify_death()
|
|
{
|
|
creat("/data/misc/vpn/abort", 0);
|
|
}
|
|
|
|
static int android_get_control_and_arguments(int *argc, char ***argv)
|
|
{
|
|
static char *args[32];
|
|
int control;
|
|
int i;
|
|
|
|
atexit(notify_death);
|
|
|
|
if ((i = android_get_control_socket("racoon")) == -1) {
|
|
return -1;
|
|
}
|
|
do_plog(LLV_DEBUG, "Waiting for control socket");
|
|
if (listen(i, 1) == -1 || (control = accept(i, NULL, 0)) == -1) {
|
|
do_plog(LLV_ERROR, "Cannot get control socket");
|
|
exit(1);
|
|
}
|
|
close(i);
|
|
fcntl(control, F_SETFD, FD_CLOEXEC);
|
|
|
|
args[0] = (*argv)[0];
|
|
for (i = 1; i < 32; ++i) {
|
|
unsigned char bytes[2];
|
|
if (recv(control, &bytes[0], 1, 0) != 1 ||
|
|
recv(control, &bytes[1], 1, 0) != 1) {
|
|
do_plog(LLV_ERROR, "Cannot get argument length");
|
|
exit(1);
|
|
} else {
|
|
int length = bytes[0] << 8 | bytes[1];
|
|
int offset = 0;
|
|
|
|
if (length == 0xFFFF) {
|
|
break;
|
|
}
|
|
args[i] = malloc(length + 1);
|
|
while (offset < length) {
|
|
int n = recv(control, &args[i][offset], length - offset, 0);
|
|
if (n > 0) {
|
|
offset += n;
|
|
} else {
|
|
do_plog(LLV_ERROR, "Cannot get argument value");
|
|
exit(1);
|
|
}
|
|
}
|
|
args[i][length] = 0;
|
|
}
|
|
}
|
|
do_plog(LLV_DEBUG, "Received %d arguments", i - 1);
|
|
|
|
*argc = i;
|
|
*argv = args;
|
|
return control;
|
|
}
|
|
|
|
const char *android_hook(char **envp)
|
|
{
|
|
struct ifreq ifr = {.ifr_flags = IFF_TUN};
|
|
int tun = open("/dev/tun", 0);
|
|
|
|
/* Android does not support INTERNAL_WINS4_LIST, so we just use it. */
|
|
while (*envp && strncmp(*envp, "INTERNAL_WINS4_LIST=", 20)) {
|
|
++envp;
|
|
}
|
|
if (!*envp) {
|
|
do_plog(LLV_ERROR, "Cannot find environment variable\n");
|
|
exit(1);
|
|
}
|
|
if (ioctl(tun, TUNSETIFF, &ifr)) {
|
|
do_plog(LLV_ERROR, "Cannot allocate TUN: %s\n", strerror(errno));
|
|
exit(1);
|
|
}
|
|
sprintf(*envp, "INTERFACE=%s", ifr.ifr_name);
|
|
return "/etc/ppp/ip-up-vpn";
|
|
}
|
|
|
|
#endif
|
|
|
|
extern void setup(int argc, char **argv);
|
|
extern void shutdown_session();
|
|
|
|
static int monitors;
|
|
static void (*callbacks[10])(int fd);
|
|
static struct pollfd pollfds[10];
|
|
|
|
char *pname;
|
|
|
|
static void terminate(int signal)
|
|
{
|
|
exit(1);
|
|
}
|
|
|
|
static void terminated()
|
|
{
|
|
do_plog(LLV_INFO, "Bye\n");
|
|
}
|
|
|
|
void monitor_fd(int fd, void (*callback)(int))
|
|
{
|
|
if (fd < 0 || monitors == 10) {
|
|
do_plog(LLV_ERROR, "Cannot monitor fd");
|
|
exit(1);
|
|
}
|
|
callbacks[monitors] = callback;
|
|
pollfds[monitors].fd = fd;
|
|
pollfds[monitors].events = callback ? POLLIN : 0;
|
|
++monitors;
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
#ifdef ANDROID_CHANGES
|
|
int control = android_get_control_and_arguments(&argc, &argv);
|
|
|
|
if (control != -1) {
|
|
pname = "%p";
|
|
monitor_fd(control, NULL);
|
|
}
|
|
#endif
|
|
|
|
do_plog(LLV_INFO, "ipsec-tools 0.7.3 (http://ipsec-tools.sf.net)\n");
|
|
|
|
signal(SIGHUP, terminate);
|
|
signal(SIGINT, terminate);
|
|
signal(SIGTERM, terminate);
|
|
signal(SIGPIPE, SIG_IGN);
|
|
atexit(terminated);
|
|
|
|
setup(argc, argv);
|
|
|
|
#ifdef ANDROID_CHANGES
|
|
shutdown(control, SHUT_WR);
|
|
#endif
|
|
|
|
while (1) {
|
|
struct timeval *tv = schedular();
|
|
int timeout = tv->tv_sec * 1000 + tv->tv_usec / 1000 + 1;
|
|
|
|
if (poll(pollfds, monitors, timeout) > 0) {
|
|
int i;
|
|
for (i = 0; i < monitors; ++i) {
|
|
if (pollfds[i].revents & POLLHUP) {
|
|
do_plog(LLV_INFO, "Connection is closed\n", pollfds[i].fd);
|
|
shutdown_session();
|
|
|
|
/* Wait for few seconds to consume late messages. */
|
|
sleep(5);
|
|
exit(1);
|
|
}
|
|
if (pollfds[i].revents & POLLIN) {
|
|
callbacks[i](pollfds[i].fd);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* plog.h */
|
|
|
|
void do_plog(int level, char *format, ...)
|
|
{
|
|
if (level >= 0 && level <= 5) {
|
|
#ifdef ANDROID_CHANGES
|
|
static int levels[6] = {
|
|
ANDROID_LOG_ERROR, ANDROID_LOG_WARN, ANDROID_LOG_INFO,
|
|
ANDROID_LOG_INFO, ANDROID_LOG_DEBUG, ANDROID_LOG_VERBOSE
|
|
};
|
|
va_list ap;
|
|
va_start(ap, format);
|
|
__android_log_vprint(levels[level], "racoon", format, ap);
|
|
va_end(ap);
|
|
#else
|
|
static char *levels = "EWNIDV";
|
|
fprintf(stderr, "%c: ", levels[level]);
|
|
va_list ap;
|
|
va_start(ap, format);
|
|
vfprintf(stderr, format, ap);
|
|
va_end(ap);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
char *binsanitize(char *data, size_t length)
|
|
{
|
|
char *output = racoon_malloc(length + 1);
|
|
if (output) {
|
|
size_t i;
|
|
for (i = 0; i < length; ++i) {
|
|
output[i] = (data[i] < ' ' || data[i] > '~') ? '?' : data[i];
|
|
}
|
|
output[length] = '\0';
|
|
}
|
|
return output;
|
|
}
|