• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
23 #include "config.h"
24 #include "gcmalloc.h"
25 #include "session.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 
android_get_control_and_arguments(int * argc,char *** argv)45 static int android_get_control_and_arguments(int *argc, char ***argv)
46 {
47     static char *args[32];
48     int control;
49     int i;
50 
51     if ((i = android_get_control_socket("racoon")) == -1) {
52         return -1;
53     }
54     do_plog(LLV_DEBUG, "Waiting for control socket");
55     if (listen(i, 1) == -1 || (control = accept(i, NULL, 0)) == -1) {
56         do_plog(LLV_ERROR, "Cannot get control socket");
57         exit(1);
58     }
59     close(i);
60     fcntl(control, F_SETFD, FD_CLOEXEC);
61 
62     args[0] = (*argv)[0];
63     for (i = 1; i < 32; ++i) {
64         unsigned char bytes[2];
65         if (recv(control, &bytes[0], 1, 0) != 1 ||
66                 recv(control, &bytes[1], 1, 0) != 1) {
67             do_plog(LLV_ERROR, "Cannot get argument length");
68             exit(1);
69         } else {
70             int length = bytes[0] << 8 | bytes[1];
71             int offset = 0;
72 
73             if (length == 0xFFFF) {
74                 break;
75             }
76             args[i] = malloc(length + 1);
77             while (offset < length) {
78                 int n = recv(control, &args[i][offset], length - offset, 0);
79                 if (n > 0) {
80                     offset += n;
81                 } else {
82                     do_plog(LLV_ERROR, "Cannot get argument value");
83                     exit(1);
84                 }
85             }
86             args[i][length] = 0;
87         }
88     }
89     do_plog(LLV_DEBUG, "Received %d arguments", i - 1);
90 
91     *argc = i;
92     *argv = args;
93     return control;
94 }
95 
android_hook(char ** envp)96 const char *android_hook(char **envp)
97 {
98     struct ifreq ifr = {.ifr_flags = IFF_TUN};
99     int tun = open("/dev/tun", 0);
100 
101     /* Android does not support INTERNAL_WINS4_LIST, so we just use it. */
102     while (*envp && strncmp(*envp, "INTERNAL_WINS4_LIST=", 20)) {
103         ++envp;
104     }
105     if (!*envp) {
106         do_plog(LLV_ERROR, "Cannot find environment variable\n");
107         exit(1);
108     }
109     if (ioctl(tun, TUNSETIFF, &ifr)) {
110         do_plog(LLV_ERROR, "Cannot allocate TUN: %s\n", strerror(errno));
111         exit(1);
112     }
113     sprintf(*envp, "INTERFACE=%s", ifr.ifr_name);
114     return "/etc/ppp/ip-up-vpn";
115 }
116 
117 #endif
118 
119 extern void setup(int argc, char **argv);
120 
121 char *pname;
122 
123 static int monitor_count;
124 static struct {
125     int (*callback)(void *ctx, int fd);
126     void *ctx;
127 } monitors[10];
128 static struct pollfd pollfds[10];
129 
terminate(int signal)130 static void terminate(int signal)
131 {
132     exit(1);
133 }
134 
terminated()135 static void terminated()
136 {
137     do_plog(LLV_INFO, "Bye\n");
138 }
139 
main(int argc,char ** argv)140 int main(int argc, char **argv)
141 {
142 #ifdef ANDROID_CHANGES
143     int control = android_get_control_and_arguments(&argc, &argv);
144     if (control != -1) {
145         pname = "%p";
146         monitor_fd(control, NULL, NULL, 0);
147     }
148 #endif
149 
150     do_plog(LLV_INFO, "ipsec-tools 0.8.0 (http://ipsec-tools.sf.net)\n");
151 
152     signal(SIGHUP, terminate);
153     signal(SIGINT, terminate);
154     signal(SIGTERM, terminate);
155     signal(SIGPIPE, SIG_IGN);
156     atexit(terminated);
157 
158     setup(argc, argv);
159 
160 #ifdef ANDROID_CHANGES
161     shutdown(control, SHUT_WR);
162     setuid(AID_VPN);
163 #endif
164 
165     while (1) {
166         struct timeval *tv = schedular();
167         int timeout = tv->tv_sec * 1000 + tv->tv_usec / 1000 + 1;
168 
169         if (poll(pollfds, monitor_count, timeout) > 0) {
170             int i;
171             for (i = 0; i < monitor_count; ++i) {
172                 if (pollfds[i].revents & POLLHUP) {
173                     do_plog(LLV_ERROR, "Connection is closed\n", pollfds[i].fd);
174                     exit(1);
175                 }
176                 if (pollfds[i].revents & POLLIN) {
177                     monitors[i].callback(monitors[i].ctx, pollfds[i].fd);
178                 }
179             }
180         }
181     }
182     return 0;
183 }
184 
185 /* session.h */
186 
monitor_fd(int fd,int (* callback)(void *,int),void * ctx,int priority)187 void monitor_fd(int fd, int (*callback)(void *, int), void *ctx, int priority)
188 {
189     if (fd < 0 || monitor_count == 10) {
190         do_plog(LLV_ERROR, "Cannot monitor fd");
191         exit(1);
192     }
193     monitors[monitor_count].callback = callback;
194     monitors[monitor_count].ctx = ctx;
195     pollfds[monitor_count].fd = fd;
196     pollfds[monitor_count].events = callback ? POLLIN : 0;
197     ++monitor_count;
198 }
199 
unmonitor_fd(int fd)200 void unmonitor_fd(int fd)
201 {
202     exit(1);
203 }
204 
205 /* plog.h */
206 
do_plog(int level,char * format,...)207 void do_plog(int level, char *format, ...)
208 {
209     if (level >= 0 && level <= 5) {
210 #ifdef ANDROID_CHANGES
211         static int levels[6] = {
212             ANDROID_LOG_ERROR, ANDROID_LOG_WARN, ANDROID_LOG_INFO,
213             ANDROID_LOG_INFO, ANDROID_LOG_DEBUG, ANDROID_LOG_VERBOSE
214         };
215         va_list ap;
216         va_start(ap, format);
217         __android_log_vprint(levels[level], "racoon", format, ap);
218         va_end(ap);
219 #else
220         static char *levels = "EWNIDV";
221         fprintf(stderr, "%c: ", levels[level]);
222         va_list ap;
223         va_start(ap, format);
224         vfprintf(stderr, format, ap);
225         va_end(ap);
226 #endif
227     }
228 }
229 
binsanitize(char * data,size_t length)230 char *binsanitize(char *data, size_t length)
231 {
232     char *output = racoon_malloc(length + 1);
233     if (output) {
234         size_t i;
235         for (i = 0; i < length; ++i) {
236             output[i] = (data[i] < ' ' || data[i] > '~') ? '?' : data[i];
237         }
238         output[length] = '\0';
239     }
240     return output;
241 }
242