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
39int the_socket = -1;
40
41extern struct protocol l2tp;
42extern struct protocol pptp;
43static struct protocol *protocols[] = {&l2tp, &pptp, NULL};
44static struct protocol *the_protocol;
45
46static char *interface;
47static int pppd_argc;
48static char **pppd_argv;
49static pid_t pppd_pid;
50
51/* We redirect signals to a pipe in order to prevent race conditions. */
52static int signals[2];
53
54static void interrupt(int signal)
55{
56    write(signals[1], &signal, sizeof(int));
57}
58
59static 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
88static 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
101static 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
154int 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
237void 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
261void 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
302void 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