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