• 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 #include "keystore_get.h"
36 #endif
37 
38 #include "mtpd.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 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 timeout = 0;
62     int i;
63 
64     for (i = 2; i < argc; ++i) {
65         if (!argv[i][0]) {
66             pppd_argc = argc - i - 1;
67             pppd_argv = &argv[i + 1];
68             argc = i;
69             break;
70         }
71     }
72 
73     if (argc >= 2) {
74         for (i = 0; protocols[i]; ++i) {
75             if (!strcmp(argv[1], protocols[i]->name)) {
76                 log_print(INFO, "Using protocol %s", protocols[i]->name);
77                 the_protocol = protocols[i];
78                 timeout = the_protocol->connect(argc - 2, &argv[2]);
79                 break;
80             }
81         }
82     }
83 
84     if (!the_protocol || timeout == -USAGE_ERROR) {
85         printf("Usage: %s <protocol-args> '' <pppd-args>, "
86                "where protocol-args are one of:\n", argv[0]);
87         for (i = 0; protocols[i]; ++i) {
88             printf("       %s %s\n", protocols[i]->name, protocols[i]->usage);
89         }
90         exit(USAGE_ERROR);
91     }
92     return timeout;
93 }
94 
stop_pppd()95 static void stop_pppd()
96 {
97     if (pppd_pid) {
98         log_print(INFO, "Sending signal to pppd (pid = %d)", pppd_pid);
99         kill(pppd_pid, SIGTERM);
100         sleep(5);
101         pppd_pid = 0;
102     }
103 }
104 
105 #ifdef ANDROID_CHANGES
106 
get_control_and_arguments(int * argc,char *** argv)107 static int get_control_and_arguments(int *argc, char ***argv)
108 {
109     static char *args[256];
110     int control;
111     int i;
112 
113     if ((i = android_get_control_socket("mtpd")) == -1) {
114         return -1;
115     }
116     log_print(DEBUG, "Waiting for control socket");
117     if (listen(i, 1) == -1 || (control = accept(i, NULL, 0)) == -1) {
118         log_print(FATAL, "Cannot get control socket");
119         exit(SYSTEM_ERROR);
120     }
121     close(i);
122     fcntl(control, F_SETFD, FD_CLOEXEC);
123 
124     args[0] = (*argv)[0];
125     for (i = 1; i < 256; ++i) {
126         unsigned char length;
127         if (recv(control, &length, 1, 0) != 1) {
128             log_print(FATAL, "Cannot get argument length");
129             exit(SYSTEM_ERROR);
130         }
131         if (length == 0xFF) {
132             break;
133         } else {
134             int offset = 0;
135             args[i] = malloc(length + 1);
136             while (offset < length) {
137                 int n = recv(control, &args[i][offset], length - offset, 0);
138                 if (n > 0) {
139                     offset += n;
140                 } else {
141                     log_print(FATAL, "Cannot get argument value");
142                     exit(SYSTEM_ERROR);
143                 }
144             }
145             args[i][length] = 0;
146         }
147     }
148     log_print(DEBUG, "Received %d arguments", i - 1);
149 
150     /* L2TP secret is the only thing stored in keystore. We do the query here
151      * so other files are clean and free from android specific code. */
152     if (i > 4 && !strcmp("l2tp", args[1]) && args[4][0]) {
153         char *value = keystore_get(args[4], NULL);
154         if (!value) {
155             log_print(FATAL, "Cannot get L2TP secret from keystore");
156             exit(SYSTEM_ERROR);
157         }
158         free(args[4]);
159         args[4] = value;
160     }
161 
162     *argc = i;
163     *argv = args;
164     return control;
165 }
166 
167 #endif
168 
main(int argc,char ** argv)169 int main(int argc, char **argv)
170 {
171     struct pollfd pollfds[2];
172     int timeout;
173     int status;
174 #ifdef ANDROID_CHANGES
175     int control = get_control_and_arguments(&argc, &argv);
176     unsigned char code = argc - 1;
177     send(control, &code, 1, 0);
178 #endif
179 
180     srandom(time(NULL));
181 
182     if (pipe(signals) == -1) {
183         log_print(FATAL, "Pipe() %s", strerror(errno));
184         exit(SYSTEM_ERROR);
185     }
186     fcntl(signals[0], F_SETFD, FD_CLOEXEC);
187     fcntl(signals[1], F_SETFD, FD_CLOEXEC);
188 
189     timeout = initialize(argc, argv);
190 
191     signal(SIGHUP, interrupt);
192     signal(SIGINT, interrupt);
193     signal(SIGTERM, interrupt);
194     signal(SIGCHLD, interrupt);
195     signal(SIGPIPE, SIG_IGN);
196     atexit(stop_pppd);
197 
198     pollfds[0].fd = signals[0];
199     pollfds[0].events = POLLIN;
200     pollfds[1].fd = the_socket;
201     pollfds[1].events = POLLIN;
202 
203     while (timeout >= 0) {
204         if (poll(pollfds, 2, timeout ? timeout : -1) == -1 && errno != EINTR) {
205             log_print(FATAL, "Poll() %s", strerror(errno));
206             exit(SYSTEM_ERROR);
207         }
208         if (pollfds[0].revents) {
209             break;
210         }
211         timeout = pollfds[1].revents ?
212             the_protocol->process() : the_protocol->timeout();
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 
235 #ifdef ANDROID_CHANGES
236     code = status;
237     send(control, &code, 1, 0);
238 #endif
239     log_print(INFO, "Mtpd is terminated (status = %d)", status);
240     return status;
241 }
242 
log_print(int level,char * format,...)243 void log_print(int level, char *format, ...)
244 {
245     if (level >= 0 && level <= LOG_MAX) {
246 #ifdef ANDROID_CHANGES
247         static int levels[5] = {
248             ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN,
249             ANDROID_LOG_ERROR, ANDROID_LOG_FATAL
250         };
251         va_list ap;
252         va_start(ap, format);
253         __android_log_vprint(levels[level], "mtpd", format, ap);
254         va_end(ap);
255 #else
256         static char *levels = "DIWEF";
257         va_list ap;
258         fprintf(stderr, "%c: ", levels[level]);
259         va_start(ap, format);
260         vfprintf(stderr, format, ap);
261         va_end(ap);
262         fputc('\n', stderr);
263 #endif
264     }
265 }
266 
create_socket(int family,int type,char * server,char * port)267 void create_socket(int family, int type, char *server, char *port)
268 {
269     struct addrinfo hints = {
270         .ai_flags = AI_NUMERICSERV,
271         .ai_family = family,
272         .ai_socktype = type,
273     };
274     struct addrinfo *records;
275     struct addrinfo *r;
276     int error;
277 
278     log_print(INFO, "Connecting to %s port %s", server, port);
279 
280     error = getaddrinfo(server, port, &hints, &records);
281     if (error) {
282         log_print(FATAL, "Getaddrinfo() %s", (error == EAI_SYSTEM) ?
283                   strerror(errno) : gai_strerror(error));
284         exit(NETWORK_ERROR);
285     }
286 
287     for (r = records; r; r = r->ai_next) {
288         the_socket = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
289         if (the_socket != -1) {
290             if (connect(the_socket, r->ai_addr, r->ai_addrlen) == 0) {
291                 break;
292             }
293             close(the_socket);
294             the_socket = -1;
295         }
296     }
297 
298     freeaddrinfo(records);
299 
300     if (the_socket == -1) {
301         log_print(FATAL, "Connect() %s", strerror(errno));
302         exit(NETWORK_ERROR);
303     }
304 
305     fcntl(the_socket, F_SETFD, FD_CLOEXEC);
306     log_print(INFO, "Connection established (socket = %d)", the_socket);
307 }
308 
start_pppd(int pppox)309 void start_pppd(int pppox)
310 {
311     if (pppd_pid) {
312         log_print(WARNING, "Pppd is already started (pid = %d)", pppd_pid);
313         close(pppox);
314         return;
315     }
316 
317     log_print(INFO, "Starting pppd (pppox = %d)", pppox);
318 
319     pppd_pid = fork();
320     if (pppd_pid < 0) {
321         log_print(FATAL, "Fork() %s", strerror(errno));
322         exit(SYSTEM_ERROR);
323     }
324 
325     if (!pppd_pid) {
326         char *args[pppd_argc + 5];
327         char number[12];
328 
329         sprintf(number, "%d", pppox);
330         args[0] = "pppd";
331         args[1] = "nodetach";
332         args[2] = "pppox";
333         args[3] = number;
334         memcpy(&args[4], pppd_argv, sizeof(char *) * pppd_argc);
335         args[4 + pppd_argc] = NULL;
336 
337         execvp("pppd", args);
338         log_print(FATAL, "Exec() %s", strerror(errno));
339         exit(1); /* Pretending a fatal error in pppd. */
340     }
341 
342     log_print(INFO, "Pppd started (pid = %d)", pppd_pid);
343     close(pppox);
344 }
345