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