• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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