1 /*
2 * Copyright (C) 2007 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 #define TRACE_TAG TRACE_ADB
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <ctype.h>
22 #include <stdarg.h>
23 #include <errno.h>
24 #include <string.h>
25 #include <time.h>
26 #include <sys/time.h>
27
28 #include "sysdeps.h"
29 #include "adb.h"
30
31 #include <private/android_filesystem_config.h>
32 #include <linux/capability.h>
33 #include <linux/prctl.h>
34
35 #if ADB_TRACE
36 ADB_MUTEX_DEFINE( D_lock );
37 #endif
38
39 int HOST = 0;
40
41 static const char *adb_device_banner = "sideload";
42
fatal(const char * fmt,...)43 void fatal(const char *fmt, ...)
44 {
45 va_list ap;
46 va_start(ap, fmt);
47 fprintf(stderr, "error: ");
48 vfprintf(stderr, fmt, ap);
49 fprintf(stderr, "\n");
50 va_end(ap);
51 exit(-1);
52 }
53
fatal_errno(const char * fmt,...)54 void fatal_errno(const char *fmt, ...)
55 {
56 va_list ap;
57 va_start(ap, fmt);
58 fprintf(stderr, "error: %s: ", strerror(errno));
59 vfprintf(stderr, fmt, ap);
60 fprintf(stderr, "\n");
61 va_end(ap);
62 exit(-1);
63 }
64
65 int adb_trace_mask;
66
67 /* read a comma/space/colum/semi-column separated list of tags
68 * from the ADB_TRACE environment variable and build the trace
69 * mask from it. note that '1' and 'all' are special cases to
70 * enable all tracing
71 */
adb_trace_init(void)72 void adb_trace_init(void)
73 {
74 const char* p = getenv("ADB_TRACE");
75 const char* q;
76
77 static const struct {
78 const char* tag;
79 int flag;
80 } tags[] = {
81 { "1", 0 },
82 { "all", 0 },
83 { "adb", TRACE_ADB },
84 { "sockets", TRACE_SOCKETS },
85 { "packets", TRACE_PACKETS },
86 { "rwx", TRACE_RWX },
87 { "usb", TRACE_USB },
88 { "sync", TRACE_SYNC },
89 { "sysdeps", TRACE_SYSDEPS },
90 { "transport", TRACE_TRANSPORT },
91 { "jdwp", TRACE_JDWP },
92 { "services", TRACE_SERVICES },
93 { NULL, 0 }
94 };
95
96 if (p == NULL)
97 return;
98
99 /* use a comma/column/semi-colum/space separated list */
100 while (*p) {
101 int len, tagn;
102
103 q = strpbrk(p, " ,:;");
104 if (q == NULL) {
105 q = p + strlen(p);
106 }
107 len = q - p;
108
109 for (tagn = 0; tags[tagn].tag != NULL; tagn++)
110 {
111 int taglen = strlen(tags[tagn].tag);
112
113 if (len == taglen && !memcmp(tags[tagn].tag, p, len) )
114 {
115 int flag = tags[tagn].flag;
116 if (flag == 0) {
117 adb_trace_mask = ~0;
118 return;
119 }
120 adb_trace_mask |= (1 << flag);
121 break;
122 }
123 }
124 p = q;
125 if (*p)
126 p++;
127 }
128 }
129
130
get_apacket(void)131 apacket *get_apacket(void)
132 {
133 apacket *p = malloc(sizeof(apacket));
134 if(p == 0) fatal("failed to allocate an apacket");
135 memset(p, 0, sizeof(apacket) - MAX_PAYLOAD);
136 return p;
137 }
138
put_apacket(apacket * p)139 void put_apacket(apacket *p)
140 {
141 free(p);
142 }
143
handle_online(void)144 void handle_online(void)
145 {
146 D("adb: online\n");
147 }
148
handle_offline(atransport * t)149 void handle_offline(atransport *t)
150 {
151 D("adb: offline\n");
152 //Close the associated usb
153 run_transport_disconnects(t);
154 }
155
156 #if TRACE_PACKETS
157 #define DUMPMAX 32
print_packet(const char * label,apacket * p)158 void print_packet(const char *label, apacket *p)
159 {
160 char *tag;
161 char *x;
162 unsigned count;
163
164 switch(p->msg.command){
165 case A_SYNC: tag = "SYNC"; break;
166 case A_CNXN: tag = "CNXN" ; break;
167 case A_OPEN: tag = "OPEN"; break;
168 case A_OKAY: tag = "OKAY"; break;
169 case A_CLSE: tag = "CLSE"; break;
170 case A_WRTE: tag = "WRTE"; break;
171 default: tag = "????"; break;
172 }
173
174 fprintf(stderr, "%s: %s %08x %08x %04x \"",
175 label, tag, p->msg.arg0, p->msg.arg1, p->msg.data_length);
176 count = p->msg.data_length;
177 x = (char*) p->data;
178 if(count > DUMPMAX) {
179 count = DUMPMAX;
180 tag = "\n";
181 } else {
182 tag = "\"\n";
183 }
184 while(count-- > 0){
185 if((*x >= ' ') && (*x < 127)) {
186 fputc(*x, stderr);
187 } else {
188 fputc('.', stderr);
189 }
190 x++;
191 }
192 fprintf(stderr, tag);
193 }
194 #endif
195
send_ready(unsigned local,unsigned remote,atransport * t)196 static void send_ready(unsigned local, unsigned remote, atransport *t)
197 {
198 D("Calling send_ready \n");
199 apacket *p = get_apacket();
200 p->msg.command = A_OKAY;
201 p->msg.arg0 = local;
202 p->msg.arg1 = remote;
203 send_packet(p, t);
204 }
205
send_close(unsigned local,unsigned remote,atransport * t)206 static void send_close(unsigned local, unsigned remote, atransport *t)
207 {
208 D("Calling send_close \n");
209 apacket *p = get_apacket();
210 p->msg.command = A_CLSE;
211 p->msg.arg0 = local;
212 p->msg.arg1 = remote;
213 send_packet(p, t);
214 }
215
send_connect(atransport * t)216 static void send_connect(atransport *t)
217 {
218 D("Calling send_connect \n");
219 apacket *cp = get_apacket();
220 cp->msg.command = A_CNXN;
221 cp->msg.arg0 = A_VERSION;
222 cp->msg.arg1 = MAX_PAYLOAD;
223 snprintf((char*) cp->data, sizeof cp->data, "%s::",
224 HOST ? "host" : adb_device_banner);
225 cp->msg.data_length = strlen((char*) cp->data) + 1;
226 send_packet(cp, t);
227 }
228
parse_banner(char * banner,atransport * t)229 void parse_banner(char *banner, atransport *t)
230 {
231 char *type, *product, *end;
232
233 D("parse_banner: %s\n", banner);
234 type = banner;
235 product = strchr(type, ':');
236 if(product) {
237 *product++ = 0;
238 } else {
239 product = "";
240 }
241
242 /* remove trailing ':' */
243 end = strchr(product, ':');
244 if(end) *end = 0;
245
246 /* save product name in device structure */
247 if (t->product == NULL) {
248 t->product = strdup(product);
249 } else if (strcmp(product, t->product) != 0) {
250 free(t->product);
251 t->product = strdup(product);
252 }
253
254 if(!strcmp(type, "bootloader")){
255 D("setting connection_state to CS_BOOTLOADER\n");
256 t->connection_state = CS_BOOTLOADER;
257 update_transports();
258 return;
259 }
260
261 if(!strcmp(type, "device")) {
262 D("setting connection_state to CS_DEVICE\n");
263 t->connection_state = CS_DEVICE;
264 update_transports();
265 return;
266 }
267
268 if(!strcmp(type, "recovery")) {
269 D("setting connection_state to CS_RECOVERY\n");
270 t->connection_state = CS_RECOVERY;
271 update_transports();
272 return;
273 }
274
275 if(!strcmp(type, "sideload")) {
276 D("setting connection_state to CS_SIDELOAD\n");
277 t->connection_state = CS_SIDELOAD;
278 update_transports();
279 return;
280 }
281
282 t->connection_state = CS_HOST;
283 }
284
handle_packet(apacket * p,atransport * t)285 void handle_packet(apacket *p, atransport *t)
286 {
287 asocket *s;
288
289 D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0],
290 ((char*) (&(p->msg.command)))[1],
291 ((char*) (&(p->msg.command)))[2],
292 ((char*) (&(p->msg.command)))[3]);
293 print_packet("recv", p);
294
295 switch(p->msg.command){
296 case A_SYNC:
297 if(p->msg.arg0){
298 send_packet(p, t);
299 if(HOST) send_connect(t);
300 } else {
301 t->connection_state = CS_OFFLINE;
302 handle_offline(t);
303 send_packet(p, t);
304 }
305 return;
306
307 case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */
308 /* XXX verify version, etc */
309 if(t->connection_state != CS_OFFLINE) {
310 t->connection_state = CS_OFFLINE;
311 handle_offline(t);
312 }
313 parse_banner((char*) p->data, t);
314 handle_online();
315 if(!HOST) send_connect(t);
316 break;
317
318 case A_OPEN: /* OPEN(local-id, 0, "destination") */
319 if(t->connection_state != CS_OFFLINE) {
320 char *name = (char*) p->data;
321 name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0;
322 s = create_local_service_socket(name);
323 if(s == 0) {
324 send_close(0, p->msg.arg0, t);
325 } else {
326 s->peer = create_remote_socket(p->msg.arg0, t);
327 s->peer->peer = s;
328 send_ready(s->id, s->peer->id, t);
329 s->ready(s);
330 }
331 }
332 break;
333
334 case A_OKAY: /* READY(local-id, remote-id, "") */
335 if(t->connection_state != CS_OFFLINE) {
336 if((s = find_local_socket(p->msg.arg1))) {
337 if(s->peer == 0) {
338 s->peer = create_remote_socket(p->msg.arg0, t);
339 s->peer->peer = s;
340 }
341 s->ready(s);
342 }
343 }
344 break;
345
346 case A_CLSE: /* CLOSE(local-id, remote-id, "") */
347 if(t->connection_state != CS_OFFLINE) {
348 if((s = find_local_socket(p->msg.arg1))) {
349 s->close(s);
350 }
351 }
352 break;
353
354 case A_WRTE:
355 if(t->connection_state != CS_OFFLINE) {
356 if((s = find_local_socket(p->msg.arg1))) {
357 unsigned rid = p->msg.arg0;
358 p->len = p->msg.data_length;
359
360 if(s->enqueue(s, p) == 0) {
361 D("Enqueue the socket\n");
362 send_ready(s->id, rid, t);
363 }
364 return;
365 }
366 }
367 break;
368
369 default:
370 printf("handle_packet: what is %08x?!\n", p->msg.command);
371 }
372
373 put_apacket(p);
374 }
375
adb_cleanup(void)376 static void adb_cleanup(void)
377 {
378 usb_cleanup();
379 }
380
adb_main()381 int adb_main()
382 {
383 atexit(adb_cleanup);
384 #if defined(HAVE_FORKEXEC)
385 // No SIGCHLD. Let the service subproc handle its children.
386 signal(SIGPIPE, SIG_IGN);
387 #endif
388
389 init_transport_registration();
390
391 // The minimal version of adbd only uses USB.
392 if (access("/dev/android_adb", F_OK) == 0) {
393 // listen on USB
394 usb_init();
395 }
396
397 if (setgid(AID_SHELL) != 0) {
398 fprintf(stderr, "failed to setgid to shell\n");
399 exit(1);
400 }
401 if (setuid(AID_SHELL) != 0) {
402 fprintf(stderr, "failed to setuid to shell\n");
403 exit(1);
404 }
405 fprintf(stderr, "userid is %d\n", getuid());
406
407 D("Event loop starting\n");
408
409 fdevent_loop();
410
411 usb_cleanup();
412
413 return 0;
414 }
415