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