179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh/*
279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh * Copyright (C) 2009 The Android Open Source Project
379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh *
479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh * Licensed under the Apache License, Version 2.0 (the "License");
579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh * you may not use this file except in compliance with the License.
679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh * You may obtain a copy of the License at
779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh *
879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh *      http://www.apache.org/licenses/LICENSE-2.0
979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh *
1079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh * Unless required by applicable law or agreed to in writing, software
1179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh * distributed under the License is distributed on an "AS IS" BASIS,
1279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh * See the License for the specific language governing permissions and
1479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh * limitations under the License.
1579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh */
1679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
1779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh#include <stdio.h>
1879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh#include <stdlib.h>
1979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh#include <stdarg.h>
2079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh#include <string.h>
2179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh#include <errno.h>
2279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh#include <sys/types.h>
2379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh#include <sys/socket.h>
2479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh#include <sys/poll.h>
2579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh#include <sys/wait.h>
2679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh#include <netdb.h>
2779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh#include <signal.h>
2879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh#include <unistd.h>
2979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh#include <fcntl.h>
3079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh#include <time.h>
3179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
3284e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh#ifdef ANDROID_CHANGES
3384e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh#include <android/log.h>
3484e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh#include <cutils/sockets.h>
3584e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh#endif
3684e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh
3779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh#include "mtpd.h"
3879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
3979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehint the_socket = -1;
4079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
4179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehextern struct protocol l2tp;
42063bb92976a72c53044c1c147fb4d1feec9716eeChia-chi Yehextern struct protocol pptp;
43063bb92976a72c53044c1c147fb4d1feec9716eeChia-chi Yehstatic struct protocol *protocols[] = {&l2tp, &pptp, NULL};
4479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehstatic struct protocol *the_protocol;
4579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
463afd73f3f230f9ea8ddce7ad354a537ade3c3030Chia-chi Yehstatic char *interface;
4779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehstatic int pppd_argc;
4879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehstatic char **pppd_argv;
4979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehstatic pid_t pppd_pid;
5079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
5179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh/* We redirect signals to a pipe in order to prevent race conditions. */
5279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehstatic int signals[2];
5379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
5479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehstatic void interrupt(int signal)
5579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh{
5679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    write(signals[1], &signal, sizeof(int));
5779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh}
5879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
5979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehstatic int initialize(int argc, char **argv)
6079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh{
6179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    int i;
6279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
637b66d20359dd1c5586ecb1594d3ee929c5b42624Chia-chi Yeh    for (i = 0; protocols[i]; ++i) {
647b66d20359dd1c5586ecb1594d3ee929c5b42624Chia-chi Yeh        struct protocol *p = protocols[i];
653afd73f3f230f9ea8ddce7ad354a537ade3c3030Chia-chi Yeh        if (argc - 3 >= p->arguments && !strcmp(argv[2], p->name)) {
667b66d20359dd1c5586ecb1594d3ee929c5b42624Chia-chi Yeh            log_print(INFO, "Using protocol %s", p->name);
677b66d20359dd1c5586ecb1594d3ee929c5b42624Chia-chi Yeh            the_protocol = p;
6879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh            break;
6979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        }
7079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
7179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
727b66d20359dd1c5586ecb1594d3ee929c5b42624Chia-chi Yeh    if (!the_protocol) {
737b66d20359dd1c5586ecb1594d3ee929c5b42624Chia-chi Yeh        printf("Usages:\n");
7479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        for (i = 0; protocols[i]; ++i) {
757b66d20359dd1c5586ecb1594d3ee929c5b42624Chia-chi Yeh            struct protocol *p = protocols[i];
763afd73f3f230f9ea8ddce7ad354a537ade3c3030Chia-chi Yeh            printf("  %s interface %s %s pppd-arguments\n",
773afd73f3f230f9ea8ddce7ad354a537ade3c3030Chia-chi Yeh                    argv[0], p->name, p->usage);
7879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        }
797b66d20359dd1c5586ecb1594d3ee929c5b42624Chia-chi Yeh        exit(0);
8079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
8179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
823afd73f3f230f9ea8ddce7ad354a537ade3c3030Chia-chi Yeh    interface = argv[1];
833afd73f3f230f9ea8ddce7ad354a537ade3c3030Chia-chi Yeh    pppd_argc = argc - 3 - the_protocol->arguments;
843afd73f3f230f9ea8ddce7ad354a537ade3c3030Chia-chi Yeh    pppd_argv = &argv[3 + the_protocol->arguments];
853afd73f3f230f9ea8ddce7ad354a537ade3c3030Chia-chi Yeh    return the_protocol->connect(&argv[3]);
8679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh}
8779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
8879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehstatic void stop_pppd()
8979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh{
9079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    if (pppd_pid) {
910269612ac00a0700997dda333faf0a3c33a388b8Chia-chi Yeh        int status;
9279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        log_print(INFO, "Sending signal to pppd (pid = %d)", pppd_pid);
9379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        kill(pppd_pid, SIGTERM);
940269612ac00a0700997dda333faf0a3c33a388b8Chia-chi Yeh        waitpid(pppd_pid, &status, 0);
9579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        pppd_pid = 0;
9679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
9779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh}
9879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
9984e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh#ifdef ANDROID_CHANGES
10084e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh
1010269612ac00a0700997dda333faf0a3c33a388b8Chia-chi Yehstatic int android_get_control_and_arguments(int *argc, char ***argv)
10284e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh{
1037b66d20359dd1c5586ecb1594d3ee929c5b42624Chia-chi Yeh    static char *args[32];
10484e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    int control;
10584e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    int i;
10684e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh
107063bb92976a72c53044c1c147fb4d1feec9716eeChia-chi Yeh    if ((i = android_get_control_socket("mtpd")) == -1) {
1080269612ac00a0700997dda333faf0a3c33a388b8Chia-chi Yeh        return -1;
109063bb92976a72c53044c1c147fb4d1feec9716eeChia-chi Yeh    }
11084e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    log_print(DEBUG, "Waiting for control socket");
111063bb92976a72c53044c1c147fb4d1feec9716eeChia-chi Yeh    if (listen(i, 1) == -1 || (control = accept(i, NULL, 0)) == -1) {
11284e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        log_print(FATAL, "Cannot get control socket");
11384e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        exit(SYSTEM_ERROR);
11484e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    }
11584e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    close(i);
1160269612ac00a0700997dda333faf0a3c33a388b8Chia-chi Yeh    fcntl(control, F_SETFD, FD_CLOEXEC);
11784e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh
11884e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    args[0] = (*argv)[0];
1197b66d20359dd1c5586ecb1594d3ee929c5b42624Chia-chi Yeh    for (i = 1; i < 32; ++i) {
12041ab620e220cfcb168f8b299e274e67d0cd37698Chia-chi Yeh        unsigned char bytes[2];
1210269612ac00a0700997dda333faf0a3c33a388b8Chia-chi Yeh        if (recv(control, &bytes[0], 1, 0) != 1 ||
1220269612ac00a0700997dda333faf0a3c33a388b8Chia-chi Yeh                recv(control, &bytes[1], 1, 0) != 1) {
12384e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            log_print(FATAL, "Cannot get argument length");
12484e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            exit(SYSTEM_ERROR);
12584e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        } else {
1260269612ac00a0700997dda333faf0a3c33a388b8Chia-chi Yeh            int length = bytes[0] << 8 | bytes[1];
12784e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            int offset = 0;
12841ab620e220cfcb168f8b299e274e67d0cd37698Chia-chi Yeh
1290269612ac00a0700997dda333faf0a3c33a388b8Chia-chi Yeh            if (length == 0xFFFF) {
1300269612ac00a0700997dda333faf0a3c33a388b8Chia-chi Yeh                break;
1310269612ac00a0700997dda333faf0a3c33a388b8Chia-chi Yeh            }
13284e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            args[i] = malloc(length + 1);
13384e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            while (offset < length) {
13484e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh                int n = recv(control, &args[i][offset], length - offset, 0);
13584e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh                if (n > 0) {
13684e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh                    offset += n;
13784e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh                } else {
13884e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh                    log_print(FATAL, "Cannot get argument value");
13984e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh                    exit(SYSTEM_ERROR);
14084e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh                }
14184e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            }
14284e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            args[i][length] = 0;
14384e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        }
14484e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    }
14584e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    log_print(DEBUG, "Received %d arguments", i - 1);
14684e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh
14784e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    *argc = i;
14884e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    *argv = args;
1490269612ac00a0700997dda333faf0a3c33a388b8Chia-chi Yeh    return control;
15084e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh}
15184e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh
15284e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh#endif
15384e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh
15479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehint main(int argc, char **argv)
15579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh{
1560269612ac00a0700997dda333faf0a3c33a388b8Chia-chi Yeh    struct pollfd pollfds[3];
1570269612ac00a0700997dda333faf0a3c33a388b8Chia-chi Yeh    int control = -1;
15879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    int timeout;
15984e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    int status;
1600269612ac00a0700997dda333faf0a3c33a388b8Chia-chi Yeh
16184e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh#ifdef ANDROID_CHANGES
1620269612ac00a0700997dda333faf0a3c33a388b8Chia-chi Yeh    control = android_get_control_and_arguments(&argc, &argv);
1630269612ac00a0700997dda333faf0a3c33a388b8Chia-chi Yeh    shutdown(control, SHUT_WR);
16484e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh#endif
16579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
16679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    srandom(time(NULL));
16779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
16879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    if (pipe(signals) == -1) {
16979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        log_print(FATAL, "Pipe() %s", strerror(errno));
17079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        exit(SYSTEM_ERROR);
17179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
1722d24765a7c081b35288838acf2a18724652fae43Chia-chi Yeh    fcntl(signals[0], F_SETFD, FD_CLOEXEC);
1732d24765a7c081b35288838acf2a18724652fae43Chia-chi Yeh    fcntl(signals[1], F_SETFD, FD_CLOEXEC);
17479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
175a7776544bd4d487667b3e55896432d255209c789Chia-chi Yeh    timeout = initialize(argc, argv);
176a7776544bd4d487667b3e55896432d255209c789Chia-chi Yeh
17779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    signal(SIGHUP, interrupt);
17879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    signal(SIGINT, interrupt);
17979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    signal(SIGTERM, interrupt);
18079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    signal(SIGCHLD, interrupt);
18179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    signal(SIGPIPE, SIG_IGN);
18279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    atexit(stop_pppd);
18379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
1840269612ac00a0700997dda333faf0a3c33a388b8Chia-chi Yeh    pollfds[0].fd = the_socket;
18579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    pollfds[0].events = POLLIN;
1860269612ac00a0700997dda333faf0a3c33a388b8Chia-chi Yeh    pollfds[1].fd = signals[0];
18779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    pollfds[1].events = POLLIN;
1880269612ac00a0700997dda333faf0a3c33a388b8Chia-chi Yeh    pollfds[2].fd = control;
1890269612ac00a0700997dda333faf0a3c33a388b8Chia-chi Yeh    pollfds[2].events = 0;
19079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
19179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    while (timeout >= 0) {
1920269612ac00a0700997dda333faf0a3c33a388b8Chia-chi Yeh        if (poll(pollfds, 3, timeout ? timeout : -1) == -1 && errno != EINTR) {
19379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh            log_print(FATAL, "Poll() %s", strerror(errno));
19479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh            exit(SYSTEM_ERROR);
19579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        }
1960269612ac00a0700997dda333faf0a3c33a388b8Chia-chi Yeh        if (pollfds[1].revents) {
19779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh            break;
19879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        }
1990269612ac00a0700997dda333faf0a3c33a388b8Chia-chi Yeh        if (pollfds[2].revents) {
2000269612ac00a0700997dda333faf0a3c33a388b8Chia-chi Yeh            interrupt(SIGTERM);
2010269612ac00a0700997dda333faf0a3c33a388b8Chia-chi Yeh        }
202fba8fdc6c588873aa944d7aa79b2f12ade78566aChia-chi Yeh        timeout = pollfds[0].revents ?
203fba8fdc6c588873aa944d7aa79b2f12ade78566aChia-chi Yeh                the_protocol->process() : the_protocol->timeout();
20435c31502e9811c7ecd430a89f2b3ae03ca7d277aChia-chi Yeh#ifdef ANDROID_CHANGES
20535c31502e9811c7ecd430a89f2b3ae03ca7d277aChia-chi Yeh        if (!access("/data/misc/vpn/abort", F_OK)) {
20635c31502e9811c7ecd430a89f2b3ae03ca7d277aChia-chi Yeh            interrupt(SIGTERM);
20735c31502e9811c7ecd430a89f2b3ae03ca7d277aChia-chi Yeh        }
208fba8fdc6c588873aa944d7aa79b2f12ade78566aChia-chi Yeh        if (!timeout) {
209fba8fdc6c588873aa944d7aa79b2f12ade78566aChia-chi Yeh            timeout = 5000;
210fba8fdc6c588873aa944d7aa79b2f12ade78566aChia-chi Yeh        }
21135c31502e9811c7ecd430a89f2b3ae03ca7d277aChia-chi Yeh#endif
21279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
21379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
21479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    if (timeout < 0) {
21584e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        status = -timeout;
21679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    } else {
21779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        int signal;
21879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        read(signals[0], &signal, sizeof(int));
21979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        log_print(INFO, "Received signal %d", signal);
22084e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        if (signal == SIGCHLD && waitpid(pppd_pid, &status, WNOHANG) == pppd_pid
221ec2b0392adedaa2707b627b842f3f9f355d844d5Chia-chi Yeh                && WIFEXITED(status)) {
22284e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            status = WEXITSTATUS(status);
22384e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            log_print(INFO, "Pppd is terminated (status = %d)", status);
22484e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            status += PPPD_EXITED;
22579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh            pppd_pid = 0;
22679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        } else {
22784e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            status = USER_REQUESTED;
22879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        }
22979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
23079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
23179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    stop_pppd();
23279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    the_protocol->shutdown();
23384e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    log_print(INFO, "Mtpd is terminated (status = %d)", status);
23484e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    return status;
23579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh}
23679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
23779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehvoid log_print(int level, char *format, ...)
23879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh{
23979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    if (level >= 0 && level <= LOG_MAX) {
24084e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh#ifdef ANDROID_CHANGES
24184e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        static int levels[5] = {
24284e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN,
24384e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            ANDROID_LOG_ERROR, ANDROID_LOG_FATAL
24484e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        };
24584e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        va_list ap;
24684e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        va_start(ap, format);
24784e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        __android_log_vprint(levels[level], "mtpd", format, ap);
24884e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        va_end(ap);
24984e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh#else
25084e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        static char *levels = "DIWEF";
25179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        va_list ap;
25279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        fprintf(stderr, "%c: ", levels[level]);
25379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        va_start(ap, format);
25479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        vfprintf(stderr, format, ap);
25579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        va_end(ap);
25679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        fputc('\n', stderr);
25784e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh#endif
25879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
25979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh}
26079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
26179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehvoid create_socket(int family, int type, char *server, char *port)
26279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh{
26379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    struct addrinfo hints = {
26479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        .ai_flags = AI_NUMERICSERV,
26579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        .ai_family = family,
26679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        .ai_socktype = type,
26779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    };
26879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    struct addrinfo *records;
26979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    struct addrinfo *r;
27079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    int error;
27179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
2723afd73f3f230f9ea8ddce7ad354a537ade3c3030Chia-chi Yeh    log_print(INFO, "Connecting to %s port %s via %s", server, port, interface);
27379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
27479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    error = getaddrinfo(server, port, &hints, &records);
27579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    if (error) {
27679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        log_print(FATAL, "Getaddrinfo() %s", (error == EAI_SYSTEM) ?
277ec2b0392adedaa2707b627b842f3f9f355d844d5Chia-chi Yeh                strerror(errno) : gai_strerror(error));
27879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        exit(NETWORK_ERROR);
27979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
28079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
28179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    for (r = records; r; r = r->ai_next) {
2823afd73f3f230f9ea8ddce7ad354a537ade3c3030Chia-chi Yeh        int s = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
2833afd73f3f230f9ea8ddce7ad354a537ade3c3030Chia-chi Yeh        if (!setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, interface,
2843afd73f3f230f9ea8ddce7ad354a537ade3c3030Chia-chi Yeh                strlen(interface)) && !connect(s, r->ai_addr, r->ai_addrlen)) {
2853afd73f3f230f9ea8ddce7ad354a537ade3c3030Chia-chi Yeh            the_socket = s;
2863afd73f3f230f9ea8ddce7ad354a537ade3c3030Chia-chi Yeh            break;
28779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        }
2883afd73f3f230f9ea8ddce7ad354a537ade3c3030Chia-chi Yeh        close(s);
28979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
29079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
29179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    freeaddrinfo(records);
29279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
29379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    if (the_socket == -1) {
29479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        log_print(FATAL, "Connect() %s", strerror(errno));
29579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        exit(NETWORK_ERROR);
29679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
29779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
29879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    fcntl(the_socket, F_SETFD, FD_CLOEXEC);
29979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    log_print(INFO, "Connection established (socket = %d)", the_socket);
30079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh}
30179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
30279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehvoid start_pppd(int pppox)
30379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh{
30479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    if (pppd_pid) {
30579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        log_print(WARNING, "Pppd is already started (pid = %d)", pppd_pid);
30679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        close(pppox);
30779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        return;
30879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
30979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
31079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    log_print(INFO, "Starting pppd (pppox = %d)", pppox);
31179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
31279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    pppd_pid = fork();
31379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    if (pppd_pid < 0) {
31479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        log_print(FATAL, "Fork() %s", strerror(errno));
31579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        exit(SYSTEM_ERROR);
31679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
31779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
31879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    if (!pppd_pid) {
31984e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        char *args[pppd_argc + 5];
32084e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        char number[12];
32179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
32279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        sprintf(number, "%d", pppox);
32384e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        args[0] = "pppd";
32484e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        args[1] = "nodetach";
32584e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        args[2] = "pppox";
32684e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        args[3] = number;
32784e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        memcpy(&args[4], pppd_argv, sizeof(char *) * pppd_argc);
32884e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        args[4 + pppd_argc] = NULL;
32979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
3304a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh#ifdef ANDROID_CHANGES
3314a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh        {
3324a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh            char envargs[65536];
3334a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh            char *tail = envargs;
3344a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh            int i;
3354a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh            /* Hex encode the arguments using [A-P] instead of [0-9A-F]. */
3364a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh            for (i = 0; args[i]; ++i) {
3374a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh                char *p = args[i];
3384a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh                do {
3394a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh                    *tail++ = 'A' + ((*p >> 4) & 0x0F);
3404a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh                    *tail++ = 'A' + (*p & 0x0F);
3414a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh                } while (*p++);
3424a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh            }
3434a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh            *tail = 0;
3444a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh            setenv("envargs", envargs, 1);
3454a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh            args[1] = NULL;
3464a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh        }
3474a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh#endif
34879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        execvp("pppd", args);
34979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        log_print(FATAL, "Exec() %s", strerror(errno));
35079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        exit(1); /* Pretending a fatal error in pppd. */
35179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
35279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
35379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    log_print(INFO, "Pppd started (pid = %d)", pppd_pid);
35479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    close(pppox);
35579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh}
356