Home | History | Annotate | Download | only in mtpd
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <stdio.h>
     18 #include <stdlib.h>
     19 #include <stdarg.h>
     20 #include <string.h>
     21 #include <errno.h>
     22 #include <sys/types.h>
     23 #include <sys/socket.h>
     24 #include <sys/poll.h>
     25 #include <sys/wait.h>
     26 #include <netdb.h>
     27 #include <signal.h>
     28 #include <unistd.h>
     29 #include <fcntl.h>
     30 #include <time.h>
     31 
     32 #ifdef ANDROID_CHANGES
     33 #include <android/log.h>
     34 #include <cutils/sockets.h>
     35 #endif
     36 
     37 #include "mtpd.h"
     38 #include "NetdClient.h"
     39 
     40 int the_socket = -1;
     41 
     42 extern struct protocol l2tp;
     43 extern struct protocol pptp;
     44 static struct protocol *protocols[] = {&l2tp, &pptp, NULL};
     45 static struct protocol *the_protocol;
     46 
     47 static char *interface;
     48 static int pppd_argc;
     49 static char **pppd_argv;
     50 static pid_t pppd_pid;
     51 
     52 /* We redirect signals to a pipe in order to prevent race conditions. */
     53 static int signals[2];
     54 
     55 static void interrupt(int signal)
     56 {
     57     write(signals[1], &signal, sizeof(int));
     58 }
     59 
     60 static int initialize(int argc, char **argv)
     61 {
     62     int i;
     63 
     64     for (i = 0; protocols[i]; ++i) {
     65         struct protocol *p = protocols[i];
     66         if (argc - 3 >= p->arguments && !strcmp(argv[2], p->name)) {
     67             log_print(INFO, "Using protocol %s", p->name);
     68             the_protocol = p;
     69             break;
     70         }
     71     }
     72 
     73     if (!the_protocol) {
     74         printf("Usages:\n");
     75         for (i = 0; protocols[i]; ++i) {
     76             struct protocol *p = protocols[i];
     77             printf("  %s interface %s %s pppd-arguments\n",
     78                     argv[0], p->name, p->usage);
     79         }
     80         exit(0);
     81     }
     82 
     83     interface = argv[1];
     84     pppd_argc = argc - 3 - the_protocol->arguments;
     85     pppd_argv = &argv[3 + the_protocol->arguments];
     86     return the_protocol->connect(&argv[3]);
     87 }
     88 
     89 static void stop_pppd()
     90 {
     91     if (pppd_pid) {
     92         int status;
     93         log_print(INFO, "Sending signal to pppd (pid = %d)", pppd_pid);
     94         kill(pppd_pid, SIGTERM);
     95         waitpid(pppd_pid, &status, 0);
     96         pppd_pid = 0;
     97     }
     98 }
     99 
    100 #ifdef ANDROID_CHANGES
    101 
    102 static int android_get_control_and_arguments(int *argc, char ***argv)
    103 {
    104     static char *args[32];
    105     int control;
    106     int i;
    107 
    108     if ((i = android_get_control_socket("mtpd")) == -1) {
    109         return -1;
    110     }
    111     log_print(DEBUG, "Waiting for control socket");
    112     if (listen(i, 1) == -1 || (control = accept(i, NULL, 0)) == -1) {
    113         log_print(FATAL, "Cannot get control socket");
    114         exit(SYSTEM_ERROR);
    115     }
    116     close(i);
    117     fcntl(control, F_SETFD, FD_CLOEXEC);
    118 
    119     args[0] = (*argv)[0];
    120     for (i = 1; i < 32; ++i) {
    121         unsigned char bytes[2];
    122         if (recv(control, &bytes[0], 1, 0) != 1 ||
    123                 recv(control, &bytes[1], 1, 0) != 1) {
    124             log_print(FATAL, "Cannot get argument length");
    125             exit(SYSTEM_ERROR);
    126         } else {
    127             int length = bytes[0] << 8 | bytes[1];
    128             int offset = 0;
    129 
    130             if (length == 0xFFFF) {
    131                 break;
    132             }
    133             args[i] = malloc(length + 1);
    134             while (offset < length) {
    135                 int n = recv(control, &args[i][offset], length - offset, 0);
    136                 if (n > 0) {
    137                     offset += n;
    138                 } else {
    139                     log_print(FATAL, "Cannot get argument value");
    140                     exit(SYSTEM_ERROR);
    141                 }
    142             }
    143             args[i][length] = 0;
    144         }
    145     }
    146     log_print(DEBUG, "Received %d arguments", i - 1);
    147 
    148     *argc = i;
    149     *argv = args;
    150     return control;
    151 }
    152 
    153 #endif
    154 
    155 int main(int argc, char **argv)
    156 {
    157     struct pollfd pollfds[3];
    158     int control = -1;
    159     int timeout;
    160     int status;
    161 
    162 #ifdef ANDROID_CHANGES
    163     control = android_get_control_and_arguments(&argc, &argv);
    164     shutdown(control, SHUT_WR);
    165 #endif
    166 
    167     srandom(time(NULL));
    168 
    169     if (pipe(signals) == -1) {
    170         log_print(FATAL, "Pipe() %s", strerror(errno));
    171         exit(SYSTEM_ERROR);
    172     }
    173     fcntl(signals[0], F_SETFD, FD_CLOEXEC);
    174     fcntl(signals[1], F_SETFD, FD_CLOEXEC);
    175 
    176     timeout = initialize(argc, argv);
    177 
    178     signal(SIGHUP, interrupt);
    179     signal(SIGINT, interrupt);
    180     signal(SIGTERM, interrupt);
    181     signal(SIGCHLD, interrupt);
    182     signal(SIGPIPE, SIG_IGN);
    183     atexit(stop_pppd);
    184 
    185     pollfds[0].fd = the_socket;
    186     pollfds[0].events = POLLIN;
    187     pollfds[1].fd = signals[0];
    188     pollfds[1].events = POLLIN;
    189     pollfds[2].fd = control;
    190     pollfds[2].events = 0;
    191 
    192     while (timeout >= 0) {
    193         if (poll(pollfds, 3, timeout ? timeout : -1) == -1 && errno != EINTR) {
    194             log_print(FATAL, "Poll() %s", strerror(errno));
    195             exit(SYSTEM_ERROR);
    196         }
    197         if (pollfds[1].revents) {
    198             break;
    199         }
    200         if (pollfds[2].revents) {
    201             interrupt(SIGTERM);
    202         }
    203         timeout = pollfds[0].revents ?
    204                 the_protocol->process() : the_protocol->timeout();
    205 #ifdef ANDROID_CHANGES
    206         if (!access("/data/misc/vpn/abort", F_OK)) {
    207             interrupt(SIGTERM);
    208         }
    209         if (!timeout) {
    210             timeout = 5000;
    211         }
    212 #endif
    213     }
    214 
    215     if (timeout < 0) {
    216         status = -timeout;
    217     } else {
    218         int signal;
    219         read(signals[0], &signal, sizeof(int));
    220         log_print(INFO, "Received signal %d", signal);
    221         if (signal == SIGCHLD && waitpid(pppd_pid, &status, WNOHANG) == pppd_pid
    222                 && WIFEXITED(status)) {
    223             status = WEXITSTATUS(status);
    224             log_print(INFO, "Pppd is terminated (status = %d)", status);
    225             status += PPPD_EXITED;
    226             pppd_pid = 0;
    227         } else {
    228             status = USER_REQUESTED;
    229         }
    230     }
    231 
    232     stop_pppd();
    233     the_protocol->shutdown();
    234     log_print(INFO, "Mtpd is terminated (status = %d)", status);
    235     return status;
    236 }
    237 
    238 void log_print(int level, char *format, ...)
    239 {
    240     if (level >= 0 && level <= LOG_MAX) {
    241 #ifdef ANDROID_CHANGES
    242         static int levels[5] = {
    243             ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN,
    244             ANDROID_LOG_ERROR, ANDROID_LOG_FATAL
    245         };
    246         va_list ap;
    247         va_start(ap, format);
    248         __android_log_vprint(levels[level], "mtpd", format, ap);
    249         va_end(ap);
    250 #else
    251         static char *levels = "DIWEF";
    252         va_list ap;
    253         fprintf(stderr, "%c: ", levels[level]);
    254         va_start(ap, format);
    255         vfprintf(stderr, format, ap);
    256         va_end(ap);
    257         fputc('\n', stderr);
    258 #endif
    259     }
    260 }
    261 
    262 void create_socket(int family, int type, char *server, char *port)
    263 {
    264     struct addrinfo hints = {
    265         .ai_flags = AI_NUMERICSERV,
    266         .ai_family = family,
    267         .ai_socktype = type,
    268     };
    269     struct addrinfo *records;
    270     struct addrinfo *r;
    271     int error;
    272 
    273     log_print(INFO, "Connecting to %s port %s via %s", server, port, interface);
    274 
    275     error = getaddrinfo(server, port, &hints, &records);
    276     if (error) {
    277         log_print(FATAL, "Getaddrinfo() %s", (error == EAI_SYSTEM) ?
    278                 strerror(errno) : gai_strerror(error));
    279         exit(NETWORK_ERROR);
    280     }
    281 
    282     for (r = records; r; r = r->ai_next) {
    283         int s = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
    284         if (!setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, interface,
    285                 strlen(interface)) && !connect(s, r->ai_addr, r->ai_addrlen)) {
    286             the_socket = s;
    287             break;
    288         }
    289         close(s);
    290     }
    291 
    292     freeaddrinfo(records);
    293 
    294     if (the_socket == -1) {
    295         log_print(FATAL, "Connect() %s", strerror(errno));
    296         exit(NETWORK_ERROR);
    297     }
    298 
    299 #ifdef ANDROID_CHANGES
    300     protectFromVpn(the_socket);
    301 #endif
    302 
    303     fcntl(the_socket, F_SETFD, FD_CLOEXEC);
    304     log_print(INFO, "Connection established (socket = %d)", the_socket);
    305 }
    306 
    307 void start_pppd(int pppox)
    308 {
    309     if (pppd_pid) {
    310         log_print(WARNING, "Pppd is already started (pid = %d)", pppd_pid);
    311         close(pppox);
    312         return;
    313     }
    314 
    315     log_print(INFO, "Starting pppd (pppox = %d)", pppox);
    316 
    317     pppd_pid = fork();
    318     if (pppd_pid < 0) {
    319         log_print(FATAL, "Fork() %s", strerror(errno));
    320         exit(SYSTEM_ERROR);
    321     }
    322 
    323     if (!pppd_pid) {
    324         char *args[pppd_argc + 5];
    325         char number[12];
    326 
    327         sprintf(number, "%d", pppox);
    328         args[0] = "pppd";
    329         args[1] = "nodetach";
    330         args[2] = "pppox";
    331         args[3] = number;
    332         memcpy(&args[4], pppd_argv, sizeof(char *) * pppd_argc);
    333         args[4 + pppd_argc] = NULL;
    334 
    335 #ifdef ANDROID_CHANGES
    336         {
    337             char envargs[65536];
    338             char *tail = envargs;
    339             int i;
    340             /* Hex encode the arguments using [A-P] instead of [0-9A-F]. */
    341             for (i = 0; args[i]; ++i) {
    342                 char *p = args[i];
    343                 do {
    344                     *tail++ = 'A' + ((*p >> 4) & 0x0F);
    345                     *tail++ = 'A' + (*p & 0x0F);
    346                 } while (*p++);
    347             }
    348             *tail = 0;
    349             setenv("envargs", envargs, 1);
    350             args[1] = NULL;
    351         }
    352 #endif
    353         execvp("pppd", args);
    354         log_print(FATAL, "Exec() %s", strerror(errno));
    355         exit(1); /* Pretending a fatal error in pppd. */
    356     }
    357 
    358     log_print(INFO, "Pppd started (pid = %d)", pppd_pid);
    359     close(pppox);
    360 }
    361