mtpd.c revision 84e3195dffa22e8d1568ef9d70aea4bcbba71a72
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;
4279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehstatic struct protocol *protocols[] = {&l2tp, NULL};
4379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehstatic struct protocol *the_protocol;
4479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
4579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehstatic int pppd_argc;
4679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehstatic char **pppd_argv;
4779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehstatic pid_t pppd_pid;
4879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
4979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh/* We redirect signals to a pipe in order to prevent race conditions. */
5079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehstatic int signals[2];
5179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
5279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehstatic void interrupt(int signal)
5379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh{
5479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    write(signals[1], &signal, sizeof(int));
5579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh}
5679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
5779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehstatic int initialize(int argc, char **argv)
5879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh{
5979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    int timeout = 0;
6079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    int i;
6179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
6279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    for (i = 2; i < argc; ++i) {
6379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        if (!argv[i][0]) {
6479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh            pppd_argc = argc - i - 1;
6579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh            pppd_argv = &argv[i + 1];
6679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh            argc = i;
6779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh            break;
6879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        }
6979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
7079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
7179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    if (argc >= 2) {
7279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        for (i = 0; protocols[i]; ++i) {
7379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh            if (!strcmp(argv[1], protocols[i]->name)) {
7479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh                log_print(INFO, "Using protocol %s", protocols[i]->name);
7579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh                the_protocol = protocols[i];
7679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh                timeout = the_protocol->connect(argc - 2, &argv[2]);
7779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh                break;
7879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh            }
7979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        }
8079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
8179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
8279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    if (!the_protocol || timeout == -USAGE_ERROR) {
8379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        printf("Usage: %s <protocol-args> '' <pppd-args>, "
8479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh               "where protocol-args are one of:\n", argv[0]);
8579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        for (i = 0; protocols[i]; ++i) {
8679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh            printf("       %s %s\n", protocols[i]->name, protocols[i]->usage);
8779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        }
8879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        exit(USAGE_ERROR);
8979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
9079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    return timeout;
9179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh}
9279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
9379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehstatic void stop_pppd()
9479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh{
9579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    if (pppd_pid) {
9679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        log_print(INFO, "Sending signal to pppd (pid = %d)", pppd_pid);
9779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        kill(pppd_pid, SIGTERM);
9879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        sleep(5);
9979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        pppd_pid = 0;
10079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
10179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh}
10279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
10384e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh#ifdef ANDROID_CHANGES
10484e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh
10584e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yehstatic int get_control_and_arguments(int *argc, char ***argv)
10684e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh{
10784e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    static char *args[256];
10884e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    int control;
10984e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    int i;
11084e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh
11184e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    log_print(DEBUG, "Waiting for control socket");
11284e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    i = android_get_control_socket("mtpd");
11384e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    if (i == -1 || listen(i, 1) == -1 || (control = accept(i, NULL, 0)) == -1) {
11484e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        log_print(FATAL, "Cannot get control socket");
11584e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        exit(SYSTEM_ERROR);
11684e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    }
11784e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    close(i);
11884e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    fcntl(control, F_SETFD, FD_CLOEXEC);
11984e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh
12084e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    args[0] = (*argv)[0];
12184e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    for (i = 1; i < 256; ++i) {
12284e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        unsigned char length;
12384e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        if (recv(control, &length, 1, 0) != 1) {
12484e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            log_print(FATAL, "Cannot get argument length");
12584e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            exit(SYSTEM_ERROR);
12684e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        }
12784e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        if (length == 0xFF) {
12884e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            break;
12984e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        } else {
13084e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            int offset = 0;
13184e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            args[i] = malloc(length + 1);
13284e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            while (offset < length) {
13384e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh                int n = recv(control, &args[i][offset], length - offset, 0);
13484e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh                if (n > 0) {
13584e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh                    offset += n;
13684e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh                } else {
13784e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh                    log_print(FATAL, "Cannot get argument value");
13884e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh                    exit(SYSTEM_ERROR);
13984e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh                }
14084e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            }
14184e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            args[i][length] = 0;
14284e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        }
14384e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    }
14484e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    log_print(DEBUG, "Received %d arguments", i - 1);
14584e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh
14684e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    *argc = i;
14784e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    *argv = args;
14884e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    return control;
14984e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh}
15084e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh
15184e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh#endif
15284e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh
15379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehint main(int argc, char **argv)
15479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh{
15579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    struct pollfd pollfds[2];
15679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    int timeout;
15784e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    int status;
15884e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh#ifdef ANDROID_CHANGES
15984e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    unsigned char code;
16084e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    int control = get_control_and_arguments(&argc, &argv);
16184e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    code = argc - 1;
16284e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    send(control, &code, 1, 0);
16384e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh#endif
16479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
16579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    srandom(time(NULL));
16679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
16779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    if (pipe(signals) == -1) {
16879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        log_print(FATAL, "Pipe() %s", strerror(errno));
16979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        exit(SYSTEM_ERROR);
17079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
17179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
17279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    signal(SIGHUP, interrupt);
17379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    signal(SIGINT, interrupt);
17479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    signal(SIGTERM, interrupt);
17579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    signal(SIGCHLD, interrupt);
17679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    signal(SIGPIPE, SIG_IGN);
17779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    atexit(stop_pppd);
17879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
17979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    timeout = initialize(argc, argv);
18079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    pollfds[0].fd = signals[0];
18179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    pollfds[0].events = POLLIN;
18279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    pollfds[1].fd = the_socket;
18379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    pollfds[1].events = POLLIN;
18479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
18579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    while (timeout >= 0) {
18679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        if (poll(pollfds, 2, timeout ? timeout : -1) == -1 && errno != EINTR) {
18779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh            log_print(FATAL, "Poll() %s", strerror(errno));
18879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh            exit(SYSTEM_ERROR);
18979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        }
19079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        if (pollfds[0].revents) {
19179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh            break;
19279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        }
19379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        timeout = pollfds[1].revents ?
19479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh            the_protocol->process() : the_protocol->timeout();
19579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
19679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
19779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    if (timeout < 0) {
19884e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        status = -timeout;
19979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    } else {
20079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        int signal;
20179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        read(signals[0], &signal, sizeof(int));
20279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        log_print(INFO, "Received signal %d", signal);
20384e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        if (signal == SIGCHLD && waitpid(pppd_pid, &status, WNOHANG) == pppd_pid
20484e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            && WIFEXITED(status)) {
20584e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            status = WEXITSTATUS(status);
20684e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            log_print(INFO, "Pppd is terminated (status = %d)", status);
20784e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            status += PPPD_EXITED;
20879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh            pppd_pid = 0;
20979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        } else {
21084e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            status = USER_REQUESTED;
21179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        }
21279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
21379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
21479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    stop_pppd();
21579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    the_protocol->shutdown();
21679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
21784e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh#ifdef ANDROID_CHANGES
21884e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    code = status;
21984e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    send(control, &code, 1, 0);
22084e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh#endif
22184e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    log_print(INFO, "Mtpd is terminated (status = %d)", status);
22284e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh    return status;
22379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh}
22479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
22579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehvoid log_print(int level, char *format, ...)
22679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh{
22779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    if (level >= 0 && level <= LOG_MAX) {
22884e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh#ifdef ANDROID_CHANGES
22984e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        static int levels[5] = {
23084e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN,
23184e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh            ANDROID_LOG_ERROR, ANDROID_LOG_FATAL
23284e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        };
23384e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        va_list ap;
23484e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        va_start(ap, format);
23584e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        __android_log_vprint(levels[level], "mtpd", format, ap);
23684e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        va_end(ap);
23784e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh#else
23884e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        static char *levels = "DIWEF";
23979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        va_list ap;
24079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        fprintf(stderr, "%c: ", levels[level]);
24179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        va_start(ap, format);
24279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        vfprintf(stderr, format, ap);
24379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        va_end(ap);
24479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        fputc('\n', stderr);
24584e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh#endif
24679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
24779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh}
24879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
24979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehvoid create_socket(int family, int type, char *server, char *port)
25079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh{
25179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    struct addrinfo hints = {
25279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        .ai_flags = AI_NUMERICSERV,
25379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        .ai_family = family,
25479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        .ai_socktype = type,
25579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    };
25679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    struct addrinfo *records;
25779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    struct addrinfo *r;
25879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    int error;
25979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
26079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    log_print(INFO, "Connecting to %s port %s", server, port);
26179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
26279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    error = getaddrinfo(server, port, &hints, &records);
26379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    if (error) {
26479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        log_print(FATAL, "Getaddrinfo() %s", (error == EAI_SYSTEM) ?
26579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh                  strerror(errno) : gai_strerror(error));
26679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        exit(NETWORK_ERROR);
26779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
26879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
26979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    for (r = records; r; r = r->ai_next) {
27079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        the_socket = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
27179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        if (the_socket != -1
27279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh            && connect(the_socket, r->ai_addr, r->ai_addrlen) == 0) {
27379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh            break;
27479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        }
27579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
27679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
27779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    freeaddrinfo(records);
27879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
27979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    if (the_socket == -1) {
28079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        log_print(FATAL, "Connect() %s", strerror(errno));
28179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        exit(NETWORK_ERROR);
28279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
28379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
28479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    fcntl(the_socket, F_SETFD, FD_CLOEXEC);
28579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    log_print(INFO, "Connection established (socket = %d)", the_socket);
28679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh}
28779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
28879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yehvoid start_pppd(int pppox)
28979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh{
29079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    if (pppd_pid) {
29179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        log_print(WARNING, "Pppd is already started (pid = %d)", pppd_pid);
29279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        close(pppox);
29379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        return;
29479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
29579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
29679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    log_print(INFO, "Starting pppd (pppox = %d)", pppox);
29779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
29879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    pppd_pid = fork();
29979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    if (pppd_pid < 0) {
30079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        log_print(FATAL, "Fork() %s", strerror(errno));
30179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        exit(SYSTEM_ERROR);
30279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
30379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
30479e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    if (!pppd_pid) {
30584e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        char *args[pppd_argc + 5];
30684e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        char number[12];
30779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
30879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        sprintf(number, "%d", pppox);
30984e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        args[0] = "pppd";
31084e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        args[1] = "nodetach";
31184e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        args[2] = "pppox";
31284e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        args[3] = number;
31384e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        memcpy(&args[4], pppd_argv, sizeof(char *) * pppd_argc);
31484e3195dffa22e8d1568ef9d70aea4bcbba71a72Chia-chi Yeh        args[4 + pppd_argc] = NULL;
31579e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
31679e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        execvp("pppd", args);
31779e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        log_print(FATAL, "Exec() %s", strerror(errno));
31879e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh        exit(1); /* Pretending a fatal error in pppd. */
31979e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    }
32079e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh
32179e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    log_print(INFO, "Pppd started (pid = %d)", pppd_pid);
32279e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh    close(pppox);
32379e6232ffa3765d3352e01e2b7887b6425c7c655Chia-chi Yeh}
324