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