blob: a504846f764eb982b467cf0870f51792dcc400ac [file] [log] [blame]
Chia-chi Yeh837a1c72009-06-26 09:40:31 +08001/*
Chia-chi Yehe9fc3762011-07-07 03:20:34 -07002 * Copyright (C) 2011 The Android Open Source Project
Chia-chi Yeh837a1c72009-06-26 09:40:31 +08003 *
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>
Chia-chi Yehbd5fa3c2009-07-07 16:24:13 +080019#include <stdarg.h>
Chia-chi Yeh837a1c72009-06-26 09:40:31 +080020#include <signal.h>
Chia-chi Yehf8a6a762011-07-04 17:21:23 -070021#include <poll.h>
Chia-chi Yeh66d08f42012-09-17 00:29:46 -070022#include <unistd.h>
Chia-chi Yehf8a6a762011-07-04 17:21:23 -070023
Chia-chi Yeh837a1c72009-06-26 09:40:31 +080024#include "config.h"
Chia-chi Yeh837a1c72009-06-26 09:40:31 +080025#include "gcmalloc.h"
Chia-chi Yeh837a1c72009-06-26 09:40:31 +080026#include "schedule.h"
Chia-chi Yehbd5fa3c2009-07-07 16:24:13 +080027#include "plog.h"
Chia-chi Yeh837a1c72009-06-26 09:40:31 +080028
Chia-chi Yeh458fe1e2009-06-26 14:36:17 +080029#ifdef ANDROID_CHANGES
30
Kenny Rootc1b51d42012-03-15 09:42:07 -070031#include <openssl/engine.h>
32
Chia-chi Yeh10700972011-07-12 18:06:57 -070033#include <string.h>
34#include <sys/types.h>
35#include <sys/socket.h>
36#include <sys/ioctl.h>
37#include <sys/stat.h>
38#include <fcntl.h>
39#include <errno.h>
40#include <linux/if.h>
41#include <linux/if_tun.h>
42
43#include <android/log.h>
44#include <cutils/sockets.h>
45#include <private/android_filesystem_config.h>
46
Chia-chi Yehcadace42011-12-08 16:22:51 -080047static void notify_death()
48{
49 creat("/data/misc/vpn/abort", 0);
50}
51
Chia-chi Yeh4dd8f6b2011-07-13 19:18:58 -070052static int android_get_control_and_arguments(int *argc, char ***argv)
Chia-chi Yeh458fe1e2009-06-26 14:36:17 +080053{
Chia-chi Yehc9ac7d22011-06-28 18:37:45 -070054 static char *args[32];
Chia-chi Yeh458fe1e2009-06-26 14:36:17 +080055 int control;
56 int i;
57
Chia-chi Yehcadace42011-12-08 16:22:51 -080058 atexit(notify_death);
59
Chia-chi Yeh458fe1e2009-06-26 14:36:17 +080060 if ((i = android_get_control_socket("racoon")) == -1) {
Chia-chi Yehe9fc3762011-07-07 03:20:34 -070061 return -1;
Chia-chi Yeh458fe1e2009-06-26 14:36:17 +080062 }
63 do_plog(LLV_DEBUG, "Waiting for control socket");
64 if (listen(i, 1) == -1 || (control = accept(i, NULL, 0)) == -1) {
65 do_plog(LLV_ERROR, "Cannot get control socket");
Chia-chi Yehf8a6a762011-07-04 17:21:23 -070066 exit(1);
Chia-chi Yeh458fe1e2009-06-26 14:36:17 +080067 }
68 close(i);
Chia-chi Yeh3724e612011-08-22 13:05:42 -070069 fcntl(control, F_SETFD, FD_CLOEXEC);
Chia-chi Yeh458fe1e2009-06-26 14:36:17 +080070
71 args[0] = (*argv)[0];
Chia-chi Yehc9ac7d22011-06-28 18:37:45 -070072 for (i = 1; i < 32; ++i) {
73 unsigned char bytes[2];
Chia-chi Yeh3724e612011-08-22 13:05:42 -070074 if (recv(control, &bytes[0], 1, 0) != 1 ||
75 recv(control, &bytes[1], 1, 0) != 1) {
Chia-chi Yeh458fe1e2009-06-26 14:36:17 +080076 do_plog(LLV_ERROR, "Cannot get argument length");
Chia-chi Yehf8a6a762011-07-04 17:21:23 -070077 exit(1);
Chia-chi Yeh458fe1e2009-06-26 14:36:17 +080078 } else {
Chia-chi Yeh3724e612011-08-22 13:05:42 -070079 int length = bytes[0] << 8 | bytes[1];
Chia-chi Yeh458fe1e2009-06-26 14:36:17 +080080 int offset = 0;
Chia-chi Yehc9ac7d22011-06-28 18:37:45 -070081
Chia-chi Yeh3724e612011-08-22 13:05:42 -070082 if (length == 0xFFFF) {
83 break;
84 }
Chia-chi Yeh458fe1e2009-06-26 14:36:17 +080085 args[i] = malloc(length + 1);
86 while (offset < length) {
87 int n = recv(control, &args[i][offset], length - offset, 0);
88 if (n > 0) {
89 offset += n;
90 } else {
91 do_plog(LLV_ERROR, "Cannot get argument value");
Chia-chi Yehf8a6a762011-07-04 17:21:23 -070092 exit(1);
Chia-chi Yeh458fe1e2009-06-26 14:36:17 +080093 }
94 }
95 args[i][length] = 0;
96 }
97 }
98 do_plog(LLV_DEBUG, "Received %d arguments", i - 1);
99
100 *argc = i;
101 *argv = args;
Chia-chi Yehe9fc3762011-07-07 03:20:34 -0700102 return control;
Chia-chi Yehc4549542009-07-22 06:46:14 +0800103}
104
Chia-chi Yeha9a07ac2011-07-19 18:29:16 -0700105const char *android_hook(char **envp)
Chia-chi Yeh10700972011-07-12 18:06:57 -0700106{
Chia-chi Yeh10700972011-07-12 18:06:57 -0700107 struct ifreq ifr = {.ifr_flags = IFF_TUN};
Chia-chi Yehdc6f5b92011-07-14 15:29:06 -0700108 int tun = open("/dev/tun", 0);
Chia-chi Yeh10700972011-07-12 18:06:57 -0700109
Chia-chi Yeha9a07ac2011-07-19 18:29:16 -0700110 /* Android does not support INTERNAL_WINS4_LIST, so we just use it. */
Chia-chi Yehdc6f5b92011-07-14 15:29:06 -0700111 while (*envp && strncmp(*envp, "INTERNAL_WINS4_LIST=", 20)) {
112 ++envp;
113 }
114 if (!*envp) {
115 do_plog(LLV_ERROR, "Cannot find environment variable\n");
116 exit(1);
117 }
Chia-chi Yeh10700972011-07-12 18:06:57 -0700118 if (ioctl(tun, TUNSETIFF, &ifr)) {
119 do_plog(LLV_ERROR, "Cannot allocate TUN: %s\n", strerror(errno));
120 exit(1);
121 }
Chia-chi Yehdc6f5b92011-07-14 15:29:06 -0700122 sprintf(*envp, "INTERFACE=%s", ifr.ifr_name);
Chia-chi Yeha9a07ac2011-07-19 18:29:16 -0700123 return "/etc/ppp/ip-up-vpn";
Chia-chi Yeh10700972011-07-12 18:06:57 -0700124}
125
Chia-chi Yeh458fe1e2009-06-26 14:36:17 +0800126#endif
127
Chia-chi Yehc4549542009-07-22 06:46:14 +0800128extern void setup(int argc, char **argv);
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700129
Chia-chi Yehc91307a2012-03-26 14:18:52 -0700130static int monitors;
131static void (*callbacks[10])(int fd);
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700132static struct pollfd pollfds[10];
Chia-chi Yehc4549542009-07-22 06:46:14 +0800133
Chia-chi Yehc91307a2012-03-26 14:18:52 -0700134char *pname;
135
Chia-chi Yehc4549542009-07-22 06:46:14 +0800136static void terminate(int signal)
137{
138 exit(1);
139}
140
141static void terminated()
142{
143 do_plog(LLV_INFO, "Bye\n");
144}
145
Chia-chi Yehc91307a2012-03-26 14:18:52 -0700146void monitor_fd(int fd, void (*callback)(int))
147{
148 if (fd < 0 || monitors == 10) {
149 do_plog(LLV_ERROR, "Cannot monitor fd");
150 exit(1);
151 }
152 callbacks[monitors] = callback;
153 pollfds[monitors].fd = fd;
154 pollfds[monitors].events = callback ? POLLIN : 0;
155 ++monitors;
156}
157
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800158int main(int argc, char **argv)
159{
Chia-chi Yehe9fc3762011-07-07 03:20:34 -0700160#ifdef ANDROID_CHANGES
Chia-chi Yeh4dd8f6b2011-07-13 19:18:58 -0700161 int control = android_get_control_and_arguments(&argc, &argv);
Adam Langleya0292812014-09-30 15:20:01 -0700162#if !defined(OPENSSL_IS_BORINGSSL)
163 ENGINE *engine;
164#endif
165
Chia-chi Yehe9fc3762011-07-07 03:20:34 -0700166 if (control != -1) {
Chia-chi Yeh8f3b3882011-07-07 13:43:20 -0700167 pname = "%p";
Chia-chi Yehc91307a2012-03-26 14:18:52 -0700168 monitor_fd(control, NULL);
Kenny Rootc1b51d42012-03-15 09:42:07 -0700169
Adam Langleya0292812014-09-30 15:20:01 -0700170#if !defined(OPENSSL_IS_BORINGSSL)
Kenny Rootc1b51d42012-03-15 09:42:07 -0700171 ENGINE_load_dynamic();
Adam Langleya0292812014-09-30 15:20:01 -0700172 engine = ENGINE_by_id("keystore");
173 if (!engine || !ENGINE_init(engine)) {
Kenny Rootc1b51d42012-03-15 09:42:07 -0700174 do_plog(LLV_ERROR, "ipsec-tools: cannot load keystore engine");
175 exit(1);
176 }
Adam Langleya0292812014-09-30 15:20:01 -0700177#endif
Chia-chi Yehe9fc3762011-07-07 03:20:34 -0700178 }
179#endif
180
Chia-chi Yehc91307a2012-03-26 14:18:52 -0700181 do_plog(LLV_INFO, "ipsec-tools 0.7.3 (http://ipsec-tools.sf.net)\n");
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800182
Chia-chi Yeh7197eb72009-07-13 16:43:29 +0800183 signal(SIGHUP, terminate);
184 signal(SIGINT, terminate);
185 signal(SIGTERM, terminate);
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800186 signal(SIGPIPE, SIG_IGN);
Chia-chi Yeh9d271b62009-07-30 17:23:56 +0800187 atexit(terminated);
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800188
Chia-chi Yeh12f44932011-07-13 16:40:15 -0700189 setup(argc, argv);
190
191#ifdef ANDROID_CHANGES
Chia-chi Yeh3724e612011-08-22 13:05:42 -0700192 shutdown(control, SHUT_WR);
Chia-chi Yeh12f44932011-07-13 16:40:15 -0700193 setuid(AID_VPN);
194#endif
195
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800196 while (1) {
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700197 struct timeval *tv = schedular();
198 int timeout = tv->tv_sec * 1000 + tv->tv_usec / 1000 + 1;
199
Chia-chi Yehc91307a2012-03-26 14:18:52 -0700200 if (poll(pollfds, monitors, timeout) > 0) {
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700201 int i;
Chia-chi Yehc91307a2012-03-26 14:18:52 -0700202 for (i = 0; i < monitors; ++i) {
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700203 if (pollfds[i].revents & POLLHUP) {
Chia-chi Yeh66d08f42012-09-17 00:29:46 -0700204 do_plog(LLV_INFO, "Connection is closed\n", pollfds[i].fd);
205 /* Wait for few seconds to consume late messages. */
206 sleep(5);
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700207 exit(1);
208 }
209 if (pollfds[i].revents & POLLIN) {
Chia-chi Yehc91307a2012-03-26 14:18:52 -0700210 callbacks[i](pollfds[i].fd);
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700211 }
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800212 }
213 }
214 }
Adam Langleya0292812014-09-30 15:20:01 -0700215
216#if !defined(OPENSSL_IS_BORINGSSL)
217 if (engine) {
218 ENGINE_finish(engine);
219 ENGINE_free(engine);
Kenny Rootc1b51d42012-03-15 09:42:07 -0700220 }
221#endif
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800222 return 0;
223}
224
225/* plog.h */
226
227void do_plog(int level, char *format, ...)
228{
Chia-chi Yeh458fe1e2009-06-26 14:36:17 +0800229 if (level >= 0 && level <= 5) {
230#ifdef ANDROID_CHANGES
231 static int levels[6] = {
232 ANDROID_LOG_ERROR, ANDROID_LOG_WARN, ANDROID_LOG_INFO,
233 ANDROID_LOG_INFO, ANDROID_LOG_DEBUG, ANDROID_LOG_VERBOSE
234 };
235 va_list ap;
236 va_start(ap, format);
237 __android_log_vprint(levels[level], "racoon", format, ap);
238 va_end(ap);
239#else
240 static char *levels = "EWNIDV";
241 fprintf(stderr, "%c: ", levels[level]);
242 va_list ap;
243 va_start(ap, format);
244 vfprintf(stderr, format, ap);
245 va_end(ap);
246#endif
247 }
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800248}
249
250char *binsanitize(char *data, size_t length)
251{
252 char *output = racoon_malloc(length + 1);
253 if (output) {
254 size_t i;
255 for (i = 0; i < length; ++i) {
Chia-chi Yehc4549542009-07-22 06:46:14 +0800256 output[i] = (data[i] < ' ' || data[i] > '~') ? '?' : data[i];
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800257 }
258 output[length] = '\0';
259 }
260 return output;
261}