mtpd.c revision 7b66d20359dd1c5586ecb1594d3ee929c5b42624
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>
35f102920925b71379dc47cead612b4374d712278aChia-chi Yeh#include "keystore_get.h"
3684e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh#endif
3784e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh
3879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh#include "mtpd.h"
3979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
4079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehint the_socket = -1;
4179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
4279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehextern struct protocol l2tp;
43063bb92976a72c53044c1c147fb4d1feec9716eeChia-chi Yehextern struct protocol pptp;
44063bb92976a72c53044c1c147fb4d1feec9716eeChia-chi Yehstatic struct protocol *protocols[] = {&l2tp, &pptp, NULL};
4579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehstatic struct protocol *the_protocol;
4679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
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];
657b66d20359dd1c5586ecb1594d3ee929c5b42624Chia-chi Yeh        if (argc - 2 >= p->arguments && !strcmp(argv[1], 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];
767b66d20359dd1c5586ecb1594d3ee929c5b42624Chia-chi Yeh            printf("  %s %s %s pppd-arguments\n", argv[0], p->name, p->usage);
7779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        }
787b66d20359dd1c5586ecb1594d3ee929c5b42624Chia-chi Yeh        exit(0);
7979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
8079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
817b66d20359dd1c5586ecb1594d3ee929c5b42624Chia-chi Yeh    pppd_argc = argc - 2 - the_protocol->arguments;
827b66d20359dd1c5586ecb1594d3ee929c5b42624Chia-chi Yeh    pppd_argv = &argv[2 + the_protocol->arguments];
837b66d20359dd1c5586ecb1594d3ee929c5b42624Chia-chi Yeh    return the_protocol->connect(&argv[2]);
8479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh}
8579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
8679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehstatic void stop_pppd()
8779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh{
8879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    if (pppd_pid) {
8979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        log_print(INFO, "Sending signal to pppd (pid = %d)", pppd_pid);
9079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        kill(pppd_pid, SIGTERM);
9179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        sleep(5);
9279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        pppd_pid = 0;
9379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
9479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh}
9579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
9684e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh#ifdef ANDROID_CHANGES
9784e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh
9884e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yehstatic int get_control_and_arguments(int *argc, char ***argv)
9984e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh{
1007b66d20359dd1c5586ecb1594d3ee929c5b42624Chia-chi Yeh    static char *args[32];
10184e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    int control;
10284e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    int i;
10384e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh
104063bb92976a72c53044c1c147fb4d1feec9716eeChia-chi Yeh    if ((i = android_get_control_socket("mtpd")) == -1) {
105063bb92976a72c53044c1c147fb4d1feec9716eeChia-chi Yeh        return -1;
106063bb92976a72c53044c1c147fb4d1feec9716eeChia-chi Yeh    }
10784e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    log_print(DEBUG, "Waiting for control socket");
108063bb92976a72c53044c1c147fb4d1feec9716eeChia-chi Yeh    if (listen(i, 1) == -1 || (control = accept(i, NULL, 0)) == -1) {
10984e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        log_print(FATAL, "Cannot get control socket");
11084e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        exit(SYSTEM_ERROR);
11184e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    }
11284e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    close(i);
11384e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    fcntl(control, F_SETFD, FD_CLOEXEC);
11484e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh
11584e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    args[0] = (*argv)[0];
1167b66d20359dd1c5586ecb1594d3ee929c5b42624Chia-chi Yeh    for (i = 1; i < 32; ++i) {
11784e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        unsigned char length;
11884e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        if (recv(control, &length, 1, 0) != 1) {
11984e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            log_print(FATAL, "Cannot get argument length");
12084e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            exit(SYSTEM_ERROR);
12184e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        }
12284e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        if (length == 0xFF) {
12384e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            break;
12484e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        } else {
12584e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            int offset = 0;
12684e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            args[i] = malloc(length + 1);
12784e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            while (offset < length) {
12884e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh                int n = recv(control, &args[i][offset], length - offset, 0);
12984e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh                if (n > 0) {
13084e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh                    offset += n;
13184e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh                } else {
13284e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh                    log_print(FATAL, "Cannot get argument value");
13384e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh                    exit(SYSTEM_ERROR);
13484e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh                }
13584e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            }
13684e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            args[i][length] = 0;
13784e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        }
13884e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    }
13984e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    log_print(DEBUG, "Received %d arguments", i - 1);
14084e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh
141f102920925b71379dc47cead612b4374d712278aChia-chi Yeh    /* L2TP secret is the only thing stored in keystore. We do the query here
142f102920925b71379dc47cead612b4374d712278aChia-chi Yeh     * so other files are clean and free from android specific code. */
143f102920925b71379dc47cead612b4374d712278aChia-chi Yeh    if (i > 4 && !strcmp("l2tp", args[1]) && args[4][0]) {
14458c35fd8e8d71912c64cb55d6e27df50dde65f76Chia-chi Yeh        char value[KEYSTORE_MESSAGE_SIZE];
145e01c97926d16201d90f2a0f1998c1276be459e5cChia-chi Yeh        int length = keystore_get(args[4], strlen(args[4]), value);
14658c35fd8e8d71912c64cb55d6e27df50dde65f76Chia-chi Yeh        if (length == -1) {
147f102920925b71379dc47cead612b4374d712278aChia-chi Yeh            log_print(FATAL, "Cannot get L2TP secret from keystore");
148f102920925b71379dc47cead612b4374d712278aChia-chi Yeh            exit(SYSTEM_ERROR);
149f102920925b71379dc47cead612b4374d712278aChia-chi Yeh        }
150f102920925b71379dc47cead612b4374d712278aChia-chi Yeh        free(args[4]);
15158c35fd8e8d71912c64cb55d6e27df50dde65f76Chia-chi Yeh        args[4] = malloc(length + 1);
15258c35fd8e8d71912c64cb55d6e27df50dde65f76Chia-chi Yeh        memcpy(args[4], value, length);
15358c35fd8e8d71912c64cb55d6e27df50dde65f76Chia-chi Yeh        args[4][length] = 0;
154f102920925b71379dc47cead612b4374d712278aChia-chi Yeh    }
155f102920925b71379dc47cead612b4374d712278aChia-chi Yeh
15684e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    *argc = i;
15784e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    *argv = args;
15884e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    return control;
15984e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh}
16084e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh
16184e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh#endif
16284e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh
16379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehint main(int argc, char **argv)
16479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh{
16579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    struct pollfd pollfds[2];
16679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    int timeout;
16784e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    int status;
16884e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh#ifdef ANDROID_CHANGES
16984e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    int control = get_control_and_arguments(&argc, &argv);
170fa04c31da4ef8765c2c8967fe548bcb55d0523d9Chia-chi Yeh    unsigned char code = argc - 1;
17184e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    send(control, &code, 1, 0);
17284e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh#endif
17379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
17479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    srandom(time(NULL));
17579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
17679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    if (pipe(signals) == -1) {
17779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        log_print(FATAL, "Pipe() %s", strerror(errno));
17879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        exit(SYSTEM_ERROR);
17979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
1802d24765a7c081b35288838acf2a18724652fae43Chia-chi Yeh    fcntl(signals[0], F_SETFD, FD_CLOEXEC);
1812d24765a7c081b35288838acf2a18724652fae43Chia-chi Yeh    fcntl(signals[1], F_SETFD, FD_CLOEXEC);
18279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
183a7776544bd4d487667b3e55896432d255209c789Chia-chi Yeh    timeout = initialize(argc, argv);
184a7776544bd4d487667b3e55896432d255209c789Chia-chi Yeh
18579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    signal(SIGHUP, interrupt);
18679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    signal(SIGINT, interrupt);
18779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    signal(SIGTERM, interrupt);
18879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    signal(SIGCHLD, interrupt);
18979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    signal(SIGPIPE, SIG_IGN);
19079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    atexit(stop_pppd);
19179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
19279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    pollfds[0].fd = signals[0];
19379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    pollfds[0].events = POLLIN;
19479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    pollfds[1].fd = the_socket;
19579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    pollfds[1].events = POLLIN;
19679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
19779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    while (timeout >= 0) {
19879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        if (poll(pollfds, 2, timeout ? timeout : -1) == -1 && errno != EINTR) {
19979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh            log_print(FATAL, "Poll() %s", strerror(errno));
20079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh            exit(SYSTEM_ERROR);
20179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        }
20279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        if (pollfds[0].revents) {
20379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh            break;
20479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        }
20579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        timeout = pollfds[1].revents ?
20679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh            the_protocol->process() : the_protocol->timeout();
20779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
20879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
20979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    if (timeout < 0) {
21084e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        status = -timeout;
21179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    } else {
21279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        int signal;
21379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        read(signals[0], &signal, sizeof(int));
21479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        log_print(INFO, "Received signal %d", signal);
21584e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        if (signal == SIGCHLD && waitpid(pppd_pid, &status, WNOHANG) == pppd_pid
21684e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            && WIFEXITED(status)) {
21784e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            status = WEXITSTATUS(status);
21884e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            log_print(INFO, "Pppd is terminated (status = %d)", status);
21984e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            status += PPPD_EXITED;
22079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh            pppd_pid = 0;
22179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        } else {
22284e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            status = USER_REQUESTED;
22379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        }
22479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
22579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
22679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    stop_pppd();
22779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    the_protocol->shutdown();
22879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
22984e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh#ifdef ANDROID_CHANGES
23084e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    code = status;
23184e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    send(control, &code, 1, 0);
23284e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh#endif
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
27279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    log_print(INFO, "Connecting to %s port %s", server, port);
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) ?
27779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-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) {
28279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        the_socket = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
283a7776544bd4d487667b3e55896432d255209c789Chia-chi Yeh        if (the_socket != -1) {
284a7776544bd4d487667b3e55896432d255209c789Chia-chi Yeh            if (connect(the_socket, r->ai_addr, r->ai_addrlen) == 0) {
285a7776544bd4d487667b3e55896432d255209c789Chia-chi Yeh                break;
286a7776544bd4d487667b3e55896432d255209c789Chia-chi Yeh            }
287a7776544bd4d487667b3e55896432d255209c789Chia-chi Yeh            close(the_socket);
288fa04c31da4ef8765c2c8967fe548bcb55d0523d9Chia-chi Yeh            the_socket = -1;
28979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        }
29079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
29179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
29279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    freeaddrinfo(records);
29379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
29479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    if (the_socket == -1) {
29579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        log_print(FATAL, "Connect() %s", strerror(errno));
29679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        exit(NETWORK_ERROR);
29779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
29879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
29979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    fcntl(the_socket, F_SETFD, FD_CLOEXEC);
30079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    log_print(INFO, "Connection established (socket = %d)", the_socket);
30179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh}
30279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
30379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehvoid start_pppd(int pppox)
30479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh{
30579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    if (pppd_pid) {
30679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        log_print(WARNING, "Pppd is already started (pid = %d)", pppd_pid);
30779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        close(pppox);
30879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        return;
30979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
31079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
31179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    log_print(INFO, "Starting pppd (pppox = %d)", pppox);
31279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
31379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    pppd_pid = fork();
31479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    if (pppd_pid < 0) {
31579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        log_print(FATAL, "Fork() %s", strerror(errno));
31679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        exit(SYSTEM_ERROR);
31779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
31879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
31979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    if (!pppd_pid) {
32084e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        char *args[pppd_argc + 5];
32184e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        char number[12];
32279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
32379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        sprintf(number, "%d", pppox);
32484e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        args[0] = "pppd";
32584e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        args[1] = "nodetach";
32684e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        args[2] = "pppox";
32784e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        args[3] = number;
32884e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        memcpy(&args[4], pppd_argv, sizeof(char *) * pppd_argc);
32984e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        args[4 + pppd_argc] = NULL;
33079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
3314a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh#ifdef ANDROID_CHANGES
3324a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh        {
3334a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh            char envargs[65536];
3344a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh            char *tail = envargs;
3354a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh            int i;
3364a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh            /* Hex encode the arguments using [A-P] instead of [0-9A-F]. */
3374a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh            for (i = 0; args[i]; ++i) {
3384a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh                char *p = args[i];
3394a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh                do {
3404a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh                    *tail++ = 'A' + ((*p >> 4) & 0x0F);
3414a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh                    *tail++ = 'A' + (*p & 0x0F);
3424a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh                } while (*p++);
3434a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh            }
3444a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh            *tail = 0;
3454a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh            setenv("envargs", envargs, 1);
3464a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh            args[1] = NULL;
3474a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh        }
3484a721df13a07ca36daafbb3785653979e3d1d393Chia-chi Yeh#endif
34979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        execvp("pppd", args);
35079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        log_print(FATAL, "Exec() %s", strerror(errno));
35179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        exit(1); /* Pretending a fatal error in pppd. */
35279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
35379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
35479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    log_print(INFO, "Pppd started (pid = %d)", pppd_pid);
35579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    close(pppox);
35679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh}
357