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
notify_death()45 static void notify_death()
46 {
47 creat("/data/misc/vpn/abort", 0);
48 }
49
android_get_control_and_arguments(int * argc,char *** argv)50 static 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
android_hook(char ** envp)103 const 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 "/system/bin/ip-up-vpn";
122 }
123
124 #endif
125
126 extern void setup(int argc, char **argv);
127 extern void shutdown_session();
128
129 static int monitors;
130 static void (*callbacks[10])(int fd);
131 static struct pollfd pollfds[10];
132
133 char *pname;
134
terminate(int signal)135 static void terminate(int signal)
136 {
137 exit(1);
138 }
139
terminated()140 static void terminated()
141 {
142 do_plog(LLV_INFO, "Bye\n");
143 }
144
monitor_fd(int fd,void (* callback)(int))145 void 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
main(int argc,char ** argv)157 int 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
do_plog(int level,char * format,...)209 void 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
binsanitize(char * data,size_t length)232 char *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