1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <stdio.h> 18#include <stdlib.h> 19#include <stdarg.h> 20#include <signal.h> 21#include <poll.h> 22#include <unistd.h> 23 24#include "config.h" 25#include "gcmalloc.h" 26#include "schedule.h" 27#include "plog.h" 28 29#ifdef ANDROID_CHANGES 30 31#include <string.h> 32#include <sys/types.h> 33#include <sys/socket.h> 34#include <sys/ioctl.h> 35#include <sys/stat.h> 36#include <fcntl.h> 37#include <errno.h> 38#include <linux/if.h> 39#include <linux/if_tun.h> 40 41#include <android/log.h> 42#include <cutils/sockets.h> 43#include <private/android_filesystem_config.h> 44 45static void notify_death() 46{ 47 creat("/data/misc/vpn/abort", 0); 48} 49 50static int android_get_control_and_arguments(int *argc, char ***argv) 51{ 52 static char *args[32]; 53 int control; 54 int i; 55 56 atexit(notify_death); 57 58 if ((i = android_get_control_socket("racoon")) == -1) { 59 return -1; 60 } 61 do_plog(LLV_DEBUG, "Waiting for control socket"); 62 if (listen(i, 1) == -1 || (control = accept(i, NULL, 0)) == -1) { 63 do_plog(LLV_ERROR, "Cannot get control socket"); 64 exit(1); 65 } 66 close(i); 67 fcntl(control, F_SETFD, FD_CLOEXEC); 68 69 args[0] = (*argv)[0]; 70 for (i = 1; i < 32; ++i) { 71 unsigned char bytes[2]; 72 if (recv(control, &bytes[0], 1, 0) != 1 || 73 recv(control, &bytes[1], 1, 0) != 1) { 74 do_plog(LLV_ERROR, "Cannot get argument length"); 75 exit(1); 76 } else { 77 int length = bytes[0] << 8 | bytes[1]; 78 int offset = 0; 79 80 if (length == 0xFFFF) { 81 break; 82 } 83 args[i] = malloc(length + 1); 84 while (offset < length) { 85 int n = recv(control, &args[i][offset], length - offset, 0); 86 if (n > 0) { 87 offset += n; 88 } else { 89 do_plog(LLV_ERROR, "Cannot get argument value"); 90 exit(1); 91 } 92 } 93 args[i][length] = 0; 94 } 95 } 96 do_plog(LLV_DEBUG, "Received %d arguments", i - 1); 97 98 *argc = i; 99 *argv = args; 100 return control; 101} 102 103const char *android_hook(char **envp) 104{ 105 struct ifreq ifr = {.ifr_flags = IFF_TUN}; 106 int tun = open("/dev/tun", 0); 107 108 /* Android does not support INTERNAL_WINS4_LIST, so we just use it. */ 109 while (*envp && strncmp(*envp, "INTERNAL_WINS4_LIST=", 20)) { 110 ++envp; 111 } 112 if (!*envp) { 113 do_plog(LLV_ERROR, "Cannot find environment variable\n"); 114 exit(1); 115 } 116 if (ioctl(tun, TUNSETIFF, &ifr)) { 117 do_plog(LLV_ERROR, "Cannot allocate TUN: %s\n", strerror(errno)); 118 exit(1); 119 } 120 sprintf(*envp, "INTERFACE=%s", ifr.ifr_name); 121 return "/etc/ppp/ip-up-vpn"; 122} 123 124#endif 125 126extern void setup(int argc, char **argv); 127extern void shutdown_session(); 128 129static int monitors; 130static void (*callbacks[10])(int fd); 131static struct pollfd pollfds[10]; 132 133char *pname; 134 135static void terminate(int signal) 136{ 137 exit(1); 138} 139 140static void terminated() 141{ 142 do_plog(LLV_INFO, "Bye\n"); 143} 144 145void monitor_fd(int fd, void (*callback)(int)) 146{ 147 if (fd < 0 || monitors == 10) { 148 do_plog(LLV_ERROR, "Cannot monitor fd"); 149 exit(1); 150 } 151 callbacks[monitors] = callback; 152 pollfds[monitors].fd = fd; 153 pollfds[monitors].events = callback ? POLLIN : 0; 154 ++monitors; 155} 156 157int main(int argc, char **argv) 158{ 159#ifdef ANDROID_CHANGES 160 int control = android_get_control_and_arguments(&argc, &argv); 161 162 if (control != -1) { 163 pname = "%p"; 164 monitor_fd(control, NULL); 165 } 166#endif 167 168 do_plog(LLV_INFO, "ipsec-tools 0.7.3 (http://ipsec-tools.sf.net)\n"); 169 170 signal(SIGHUP, terminate); 171 signal(SIGINT, terminate); 172 signal(SIGTERM, terminate); 173 signal(SIGPIPE, SIG_IGN); 174 atexit(terminated); 175 176 setup(argc, argv); 177 178#ifdef ANDROID_CHANGES 179 shutdown(control, SHUT_WR); 180#endif 181 182 while (1) { 183 struct timeval *tv = schedular(); 184 int timeout = tv->tv_sec * 1000 + tv->tv_usec / 1000 + 1; 185 186 if (poll(pollfds, monitors, timeout) > 0) { 187 int i; 188 for (i = 0; i < monitors; ++i) { 189 if (pollfds[i].revents & POLLHUP) { 190 do_plog(LLV_INFO, "Connection is closed\n", pollfds[i].fd); 191 shutdown_session(); 192 193 /* Wait for few seconds to consume late messages. */ 194 sleep(5); 195 exit(1); 196 } 197 if (pollfds[i].revents & POLLIN) { 198 callbacks[i](pollfds[i].fd); 199 } 200 } 201 } 202 } 203 204 return 0; 205} 206 207/* plog.h */ 208 209void do_plog(int level, char *format, ...) 210{ 211 if (level >= 0 && level <= 5) { 212#ifdef ANDROID_CHANGES 213 static int levels[6] = { 214 ANDROID_LOG_ERROR, ANDROID_LOG_WARN, ANDROID_LOG_INFO, 215 ANDROID_LOG_INFO, ANDROID_LOG_DEBUG, ANDROID_LOG_VERBOSE 216 }; 217 va_list ap; 218 va_start(ap, format); 219 __android_log_vprint(levels[level], "racoon", format, ap); 220 va_end(ap); 221#else 222 static char *levels = "EWNIDV"; 223 fprintf(stderr, "%c: ", levels[level]); 224 va_list ap; 225 va_start(ap, format); 226 vfprintf(stderr, format, ap); 227 va_end(ap); 228#endif 229 } 230} 231 232char *binsanitize(char *data, size_t length) 233{ 234 char *output = racoon_malloc(length + 1); 235 if (output) { 236 size_t i; 237 for (i = 0; i < length; ++i) { 238 output[i] = (data[i] < ' ' || data[i] > '~') ? '?' : data[i]; 239 } 240 output[length] = '\0'; 241 } 242 return output; 243} 244