blob: e03d89d075917c1dc07ab090c7b56cd5739c2a9c [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);
Kenny Rootc1b51d42012-03-15 09:42:07 -0700162 ENGINE *e;
Chia-chi Yehe9fc3762011-07-07 03:20:34 -0700163 if (control != -1) {
Chia-chi Yeh8f3b3882011-07-07 13:43:20 -0700164 pname = "%p";
Chia-chi Yehc91307a2012-03-26 14:18:52 -0700165 monitor_fd(control, NULL);
Kenny Rootc1b51d42012-03-15 09:42:07 -0700166
167 ENGINE_load_dynamic();
168 e = ENGINE_by_id("keystore");
169 if (!e || !ENGINE_init(e)) {
170 do_plog(LLV_ERROR, "ipsec-tools: cannot load keystore engine");
171 exit(1);
172 }
Chia-chi Yehe9fc3762011-07-07 03:20:34 -0700173 }
174#endif
175
Chia-chi Yehc91307a2012-03-26 14:18:52 -0700176 do_plog(LLV_INFO, "ipsec-tools 0.7.3 (http://ipsec-tools.sf.net)\n");
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800177
Chia-chi Yeh7197eb72009-07-13 16:43:29 +0800178 signal(SIGHUP, terminate);
179 signal(SIGINT, terminate);
180 signal(SIGTERM, terminate);
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800181 signal(SIGPIPE, SIG_IGN);
Chia-chi Yeh9d271b62009-07-30 17:23:56 +0800182 atexit(terminated);
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800183
Chia-chi Yeh12f44932011-07-13 16:40:15 -0700184 setup(argc, argv);
185
186#ifdef ANDROID_CHANGES
Chia-chi Yeh3724e612011-08-22 13:05:42 -0700187 shutdown(control, SHUT_WR);
Chia-chi Yeh12f44932011-07-13 16:40:15 -0700188 setuid(AID_VPN);
189#endif
190
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800191 while (1) {
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700192 struct timeval *tv = schedular();
193 int timeout = tv->tv_sec * 1000 + tv->tv_usec / 1000 + 1;
194
Chia-chi Yehc91307a2012-03-26 14:18:52 -0700195 if (poll(pollfds, monitors, timeout) > 0) {
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700196 int i;
Chia-chi Yehc91307a2012-03-26 14:18:52 -0700197 for (i = 0; i < monitors; ++i) {
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700198 if (pollfds[i].revents & POLLHUP) {
Chia-chi Yeh66d08f42012-09-17 00:29:46 -0700199 do_plog(LLV_INFO, "Connection is closed\n", pollfds[i].fd);
200 /* Wait for few seconds to consume late messages. */
201 sleep(5);
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700202 exit(1);
203 }
204 if (pollfds[i].revents & POLLIN) {
Chia-chi Yehc91307a2012-03-26 14:18:52 -0700205 callbacks[i](pollfds[i].fd);
Chia-chi Yehf8a6a762011-07-04 17:21:23 -0700206 }
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800207 }
208 }
209 }
Kenny Rootc1b51d42012-03-15 09:42:07 -0700210#ifdef ANDROID_CHANGES
211 if (e) {
212 ENGINE_finish(e);
213 ENGINE_free(e);
214 }
215#endif
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800216 return 0;
217}
218
219/* plog.h */
220
221void do_plog(int level, char *format, ...)
222{
Chia-chi Yeh458fe1e2009-06-26 14:36:17 +0800223 if (level >= 0 && level <= 5) {
224#ifdef ANDROID_CHANGES
225 static int levels[6] = {
226 ANDROID_LOG_ERROR, ANDROID_LOG_WARN, ANDROID_LOG_INFO,
227 ANDROID_LOG_INFO, ANDROID_LOG_DEBUG, ANDROID_LOG_VERBOSE
228 };
229 va_list ap;
230 va_start(ap, format);
231 __android_log_vprint(levels[level], "racoon", format, ap);
232 va_end(ap);
233#else
234 static char *levels = "EWNIDV";
235 fprintf(stderr, "%c: ", levels[level]);
236 va_list ap;
237 va_start(ap, format);
238 vfprintf(stderr, format, ap);
239 va_end(ap);
240#endif
241 }
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800242}
243
244char *binsanitize(char *data, size_t length)
245{
246 char *output = racoon_malloc(length + 1);
247 if (output) {
248 size_t i;
249 for (i = 0; i < length; ++i) {
Chia-chi Yehc4549542009-07-22 06:46:14 +0800250 output[i] = (data[i] < ' ' || data[i] > '~') ? '?' : data[i];
Chia-chi Yeh837a1c72009-06-26 09:40:31 +0800251 }
252 output[length] = '\0';
253 }
254 return output;
255}