• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 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 <string.h>
21 #include <errno.h>
22 #include <sys/types.h>
23 #include <sys/socket.h>
24 #include <sys/poll.h>
25 #include <sys/wait.h>
26 #include <netdb.h>
27 #include <signal.h>
28 #include <unistd.h>
29 #include <fcntl.h>
30 #include <time.h>
31 
32 #ifdef ANDROID_CHANGES
33 #include <android/log.h>
34 #include <cutils/sockets.h>
35 #endif
36 
37 #include "mtpd.h"
38 
39 int the_socket = -1;
40 
41 extern struct protocol l2tp;
42 extern struct protocol pptp;
43 static struct protocol *protocols[] = {&l2tp, &pptp, NULL};
44 static struct protocol *the_protocol;
45 
46 static char *interface;
47 static int pppd_argc;
48 static char **pppd_argv;
49 static pid_t pppd_pid;
50 
51 /* We redirect signals to a pipe in order to prevent race conditions. */
52 static int signals[2];
53 
interrupt(int signal)54 static void interrupt(int signal)
55 {
56     write(signals[1], &signal, sizeof(int));
57 }
58 
initialize(int argc,char ** argv)59 static int initialize(int argc, char **argv)
60 {
61     int i;
62 
63     for (i = 0; protocols[i]; ++i) {
64         struct protocol *p = protocols[i];
65         if (argc - 3 >= p->arguments && !strcmp(argv[2], p->name)) {
66             log_print(INFO, "Using protocol %s", p->name);
67             the_protocol = p;
68             break;
69         }
70     }
71 
72     if (!the_protocol) {
73         printf("Usages:\n");
74         for (i = 0; protocols[i]; ++i) {
75             struct protocol *p = protocols[i];
76             printf("  %s interface %s %s pppd-arguments\n",
77                     argv[0], p->name, p->usage);
78         }
79         exit(0);
80     }
81 
82     interface = argv[1];
83     pppd_argc = argc - 3 - the_protocol->arguments;
84     pppd_argv = &argv[3 + the_protocol->arguments];
85     return the_protocol->connect(&argv[3]);
86 }
87 
stop_pppd()88 static void stop_pppd()
89 {
90     if (pppd_pid) {
91         int status;
92         log_print(INFO, "Sending signal to pppd (pid = %d)", pppd_pid);
93         kill(pppd_pid, SIGTERM);
94         waitpid(pppd_pid, &status, 0);
95         pppd_pid = 0;
96     }
97 }
98 
99 #ifdef ANDROID_CHANGES
100 
android_get_control_and_arguments(int * argc,char *** argv)101 static int android_get_control_and_arguments(int *argc, char ***argv)
102 {
103     static char *args[32];
104     int control;
105     int i;
106 
107     if ((i = android_get_control_socket("mtpd")) == -1) {
108         return -1;
109     }
110     log_print(DEBUG, "Waiting for control socket");
111     if (listen(i, 1) == -1 || (control = accept(i, NULL, 0)) == -1) {
112         log_print(FATAL, "Cannot get control socket");
113         exit(SYSTEM_ERROR);
114     }
115     close(i);
116     fcntl(control, F_SETFD, FD_CLOEXEC);
117 
118     args[0] = (*argv)[0];
119     for (i = 1; i < 32; ++i) {
120         unsigned char bytes[2];
121         if (recv(control, &bytes[0], 1, 0) != 1 ||
122                 recv(control, &bytes[1], 1, 0) != 1) {
123             log_print(FATAL, "Cannot get argument length");
124             exit(SYSTEM_ERROR);
125         } else {
126             int length = bytes[0] << 8 | bytes[1];
127             int offset = 0;
128 
129             if (length == 0xFFFF) {
130                 break;
131             }
132             args[i] = malloc(length + 1);
133             while (offset < length) {
134                 int n = recv(control, &args[i][offset], length - offset, 0);
135                 if (n > 0) {
136                     offset += n;
137                 } else {
138                     log_print(FATAL, "Cannot get argument value");
139                     exit(SYSTEM_ERROR);
140                 }
141             }
142             args[i][length] = 0;
143         }
144     }
145     log_print(DEBUG, "Received %d arguments", i - 1);
146 
147     *argc = i;
148     *argv = args;
149     return control;
150 }
151 
152 #endif
153 
main(int argc,char ** argv)154 int main(int argc, char **argv)
155 {
156     struct pollfd pollfds[3];
157     int control = -1;
158     int timeout;
159     int status;
160 
161 #ifdef ANDROID_CHANGES
162     control = android_get_control_and_arguments(&argc, &argv);
163     shutdown(control, SHUT_WR);
164 #endif
165 
166     srandom(time(NULL));
167 
168     if (pipe(signals) == -1) {
169         log_print(FATAL, "Pipe() %s", strerror(errno));
170         exit(SYSTEM_ERROR);
171     }
172     fcntl(signals[0], F_SETFD, FD_CLOEXEC);
173     fcntl(signals[1], F_SETFD, FD_CLOEXEC);
174 
175     timeout = initialize(argc, argv);
176 
177     signal(SIGHUP, interrupt);
178     signal(SIGINT, interrupt);
179     signal(SIGTERM, interrupt);
180     signal(SIGCHLD, interrupt);
181     signal(SIGPIPE, SIG_IGN);
182     atexit(stop_pppd);
183 
184     pollfds[0].fd = the_socket;
185     pollfds[0].events = POLLIN;
186     pollfds[1].fd = signals[0];
187     pollfds[1].events = POLLIN;
188     pollfds[2].fd = control;
189     pollfds[2].events = 0;
190 
191     while (timeout >= 0) {
192         if (poll(pollfds, 3, timeout ? timeout : -1) == -1 && errno != EINTR) {
193             log_print(FATAL, "Poll() %s", strerror(errno));
194             exit(SYSTEM_ERROR);
195         }
196         if (pollfds[1].revents) {
197             break;
198         }
199         if (pollfds[2].revents) {
200             interrupt(SIGTERM);
201         }
202         timeout = pollfds[0].revents ?
203                 the_protocol->process() : the_protocol->timeout();
204 #ifdef ANDROID_CHANGES
205         if (!access("/data/misc/vpn/abort", F_OK)) {
206             interrupt(SIGTERM);
207         }
208         if (!timeout) {
209             timeout = 5000;
210         }
211 #endif
212     }
213 
214     if (timeout < 0) {
215         status = -timeout;
216     } else {
217         int signal;
218         read(signals[0], &signal, sizeof(int));
219         log_print(INFO, "Received signal %d", signal);
220         if (signal == SIGCHLD && waitpid(pppd_pid, &status, WNOHANG) == pppd_pid
221                 && WIFEXITED(status)) {
222             status = WEXITSTATUS(status);
223             log_print(INFO, "Pppd is terminated (status = %d)", status);
224             status += PPPD_EXITED;
225             pppd_pid = 0;
226         } else {
227             status = USER_REQUESTED;
228         }
229     }
230 
231     stop_pppd();
232     the_protocol->shutdown();
233     log_print(INFO, "Mtpd is terminated (status = %d)", status);
234     return status;
235 }
236 
log_print(int level,char * format,...)237 void log_print(int level, char *format, ...)
238 {
239     if (level >= 0 && level <= LOG_MAX) {
240 #ifdef ANDROID_CHANGES
241         static int levels[5] = {
242             ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN,
243             ANDROID_LOG_ERROR, ANDROID_LOG_FATAL
244         };
245         va_list ap;
246         va_start(ap, format);
247         __android_log_vprint(levels[level], "mtpd", format, ap);
248         va_end(ap);
249 #else
250         static char *levels = "DIWEF";
251         va_list ap;
252         fprintf(stderr, "%c: ", levels[level]);
253         va_start(ap, format);
254         vfprintf(stderr, format, ap);
255         va_end(ap);
256         fputc('\n', stderr);
257 #endif
258     }
259 }
260 
create_socket(int family,int type,char * server,char * port)261 void create_socket(int family, int type, char *server, char *port)
262 {
263     struct addrinfo hints = {
264         .ai_flags = AI_NUMERICSERV,
265         .ai_family = family,
266         .ai_socktype = type,
267     };
268     struct addrinfo *records;
269     struct addrinfo *r;
270     int error;
271 
272     log_print(INFO, "Connecting to %s port %s via %s", server, port, interface);
273 
274     error = getaddrinfo(server, port, &hints, &records);
275     if (error) {
276         log_print(FATAL, "Getaddrinfo() %s", (error == EAI_SYSTEM) ?
277                 strerror(errno) : gai_strerror(error));
278         exit(NETWORK_ERROR);
279     }
280 
281     for (r = records; r; r = r->ai_next) {
282         int s = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
283         if (!setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, interface,
284                 strlen(interface)) && !connect(s, r->ai_addr, r->ai_addrlen)) {
285             the_socket = s;
286             break;
287         }
288         close(s);
289     }
290 
291     freeaddrinfo(records);
292 
293     if (the_socket == -1) {
294         log_print(FATAL, "Connect() %s", strerror(errno));
295         exit(NETWORK_ERROR);
296     }
297 
298     fcntl(the_socket, F_SETFD, FD_CLOEXEC);
299     log_print(INFO, "Connection established (socket = %d)", the_socket);
300 }
301 
start_pppd(int pppox)302 void start_pppd(int pppox)
303 {
304     if (pppd_pid) {
305         log_print(WARNING, "Pppd is already started (pid = %d)", pppd_pid);
306         close(pppox);
307         return;
308     }
309 
310     log_print(INFO, "Starting pppd (pppox = %d)", pppox);
311 
312     pppd_pid = fork();
313     if (pppd_pid < 0) {
314         log_print(FATAL, "Fork() %s", strerror(errno));
315         exit(SYSTEM_ERROR);
316     }
317 
318     if (!pppd_pid) {
319         char *args[pppd_argc + 5];
320         char number[12];
321 
322         sprintf(number, "%d", pppox);
323         args[0] = "pppd";
324         args[1] = "nodetach";
325         args[2] = "pppox";
326         args[3] = number;
327         memcpy(&args[4], pppd_argv, sizeof(char *) * pppd_argc);
328         args[4 + pppd_argc] = NULL;
329 
330 #ifdef ANDROID_CHANGES
331         {
332             char envargs[65536];
333             char *tail = envargs;
334             int i;
335             /* Hex encode the arguments using [A-P] instead of [0-9A-F]. */
336             for (i = 0; args[i]; ++i) {
337                 char *p = args[i];
338                 do {
339                     *tail++ = 'A' + ((*p >> 4) & 0x0F);
340                     *tail++ = 'A' + (*p & 0x0F);
341                 } while (*p++);
342             }
343             *tail = 0;
344             setenv("envargs", envargs, 1);
345             args[1] = NULL;
346         }
347 #endif
348         execvp("pppd", args);
349         log_print(FATAL, "Exec() %s", strerror(errno));
350         exit(1); /* Pretending a fatal error in pppd. */
351     }
352 
353     log_print(INFO, "Pppd started (pid = %d)", pppd_pid);
354     close(pppox);
355 }
356