2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 //#define TRACE_TAG TRACE_SDB
18 #define LOG_TAG "SDBD_TRACE_SDB"
32 #include <tzplatform_config.h>
35 #include <sys/smack.h>
41 #include "commandline_sdbd.h"
45 #include "sdbd_plugin.h"
46 #include "sdb_systemd.h"
48 #ifdef SUPPORT_ENCRYPT
49 #include "plugin_encrypt.h"
52 #include <linux/prctl.h>
53 #include <system_info.h>
57 #define PROC_CMDLINE_PATH "/proc/cmdline"
58 #define USB_SERIAL_PATH "/sys/class/usb_mode/usb0/iSerial"
59 #define APPID2PID_PATH "/usr/bin/appid2pid"
61 #include <sys/ioctl.h>
63 #include <netinet/in.h>
64 #include <arpa/inet.h>
65 #define GUEST_IP_INTERFACE "eth0"
67 #include "unordered_ptr_set.h"
69 SDB_MUTEX_DEFINE(zone_check_lock);
71 SDB_MUTEX_DEFINE( D_lock );
74 #define SDB_LOGCONF_PATH "/tmp/.sdbdlog.conf"
77 int exit_cleanup_required = 0;
82 char* g_sdk_home_dir = NULL;
83 char* g_sdk_home_dir_env = NULL;
85 int rootshell_mode; // 0: sdk user, 1: root
86 int booting_done; // 0: platform booting is in progess 1: platform booting is done
90 gid_t g_root_group_id;
91 char* g_root_home_dir = NULL;
92 char* g_root_home_dir_env = NULL;
99 struct group_info g_default_groups[] = {
100 {"priv_externalstorage", -1},
101 {"priv_externalstorage_appdata", -1},
102 {"priv_mediastorage", -1},
107 #define SDB_DEFAULT_GROUPS_CNT ((sizeof(g_default_groups)/sizeof(g_default_groups[0]))-1)
108 #define BUF_SIZE 4096
110 int is_init_sdk_userinfo = 0;
111 int is_pwlocked = 0; // 0 if unlocked, 1 otherwise
113 int recovery_mode = 0;
115 SdbdCommandlineArgs sdbd_commandline_args;
117 static int is_support_usbproto();
118 static int is_support_sockproto();
120 void (*usb_init)() = NULL;
121 void (*usb_cleanup)() = NULL;
122 int (*usb_write)(usb_handle *h, const void *data, int len) = NULL;
123 int (*usb_read)(usb_handle *h, void *data, size_t len) = NULL;
124 int (*usb_close)(usb_handle *h) = NULL;
125 void (*usb_kick)(usb_handle *h) = NULL;
127 int g_is_emulator = -1;
128 int is_emulator(void) {
129 if (g_is_emulator >= 0) {
130 return g_is_emulator;
132 D("failed to initialize check emulator\n");
135 return sdbd_commandline_args.emulator.host != NULL;
138 int is_appid2pid_supported(void) {
140 if (access(APPID2PID_PATH, F_OK) == 0) {
141 /* It is necessary to confirm that it is possible
142 * to run "appid2pid" in the sdk user/group privileges. */
144 if (stat(APPID2PID_PATH, &st) == 0) {
145 D("appid2pid uid=%d, gid=%d, mode=0x%x.\n", st.st_uid, st.st_gid, st.st_mode);
146 if ( (st.st_uid == STATIC_SDK_USER_ID && st.st_mode & S_IXUSR)
147 || (st.st_gid == STATIC_SDK_GROUP_ID && st.st_mode & S_IXGRP)
148 || (st.st_mode & S_IXOTH) ) {
149 D("appid2pid is supported.\n");
154 D("failed to access appid2pid file: %d\n", errno);
157 D("appid2pid is NOT supported.\n");
161 int is_netcoredbg_supported(void) {
163 FILE *fp = fopen(NETCOREDBG_LOCATION, "r");
169 while ((num = getline(&line, &len, fp)) != -1) {
170 if (strstr(line, "NETCOREDBG") != NULL) {
171 snprintf(g_capabilities.netcoredbg_support, sizeof(g_capabilities.netcoredbg_support),
185 const char* get_platfrom_architecture(void) {
187 D("void pointer size: %zu", sizeof(void_pointer));
188 // in 32 bit sizeof void* is 4 and in 64 bit its 8
189 if((int)(sizeof(void_pointer)) == 4)
191 if((int)(sizeof(void_pointer)) == 8)
196 int is_container_enabled(void) {
199 ret = system_info_get_platform_bool("tizen.org/feature/container", &value);
200 if (ret != SYSTEM_INFO_ERROR_NONE) {
201 E("failed to get container information: %d\n", errno);
204 D("tizen container: %d\n", value);
213 static const char *sdb_device_banner = "device";
215 void fatal(const char *fmt, ...)
219 fprintf(stderr, "error: ");
220 vfprintf(stderr, fmt, ap);
221 fprintf(stderr, "\n");
226 void fatal_errno(const char *fmt, ...)
230 fprintf(stderr, "errno: %d: ", errno);
231 vfprintf(stderr, fmt, ap);
232 fprintf(stderr, "\n");
237 static char* get_sdb_log_conf(const char* key)
240 char line[256] = {0,};
241 char value[256] = {0,};
243 if (access(SDB_LOGCONF_PATH, F_OK)) {
247 fd = unix_open(SDB_LOGCONF_PATH, O_RDONLY);
249 E("failed to open '%s' file: %d\n", SDB_LOGCONF_PATH, errno);
253 if (read_line(fd, line, sizeof(line)) > 0) {
254 char* start = strstr(line, key);
256 // move one more character to remove '=',
257 // including the length of the key string
258 start = start + strlen(key) + 1;
259 char* end = strstr(start, " ");
261 strncpy(value, start, end - start);
263 strncpy(value, start, sizeof(value) - 1);
264 value[sizeof(value) - 1] = '\0';
272 return strdup(value);
275 static int is_enable_sdbd_log()
277 return (!strncmp(g_capabilities.log_enable, PLUGIN_RET_ENABLED, strlen(PLUGIN_RET_ENABLED)+1));
282 /* read a comma/space/colum/semi-column separated list of tags
283 * from the SDB_TRACE environment variable and build the trace
284 * mask from it. note that '1' and 'all' are special cases to
287 void sdb_trace_init(void)
289 char* ptr = get_sdb_log_conf("SDB_TRACE");
293 static const struct {
299 { "sdb", TRACE_SDB },
300 { "sockets", TRACE_SOCKETS },
301 { "packets", TRACE_PACKETS },
302 { "rwx", TRACE_RWX },
303 { "usb", TRACE_USB },
304 { "sync", TRACE_SYNC },
305 { "sysdeps", TRACE_SYSDEPS },
306 { "transport", TRACE_TRANSPORT },
307 { "jdwp", TRACE_JDWP },
308 { "services", TRACE_SERVICES },
309 { "properties", TRACE_PROPERTIES },
310 { "sdktools", TRACE_SDKTOOLS },
311 { "appcmd", TRACE_APPCMD },
316 if (is_enable_sdbd_log())
324 /* use a comma/column/semi-colum/space separated list */
328 q = strpbrk(p, " ,:;");
334 for (tagn = 0; tags[tagn].tag != NULL; tagn++)
336 int taglen = strlen(tags[tagn].tag);
338 if (len == taglen && !memcmp(tags[tagn].tag, p, len) )
340 int flag = tags[tagn].flag;
346 sdb_trace_mask |= (1 << flag);
358 * Implements SDB tracing inside the emulator.
364 * Redefine open and write for qemu_pipe.h that contains inlined references
365 * to those routines. We will redifine them back after qemu_pipe.h inclusion.
370 #define open sdb_open
371 #define write sdb_write
372 #include "qemu_pipe.h"
375 #define open ___xxx_open
376 #define write ___xxx_write
378 /* A handle to sdb-debug qemud service in the emulator. */
379 int sdb_debug_qemu = -1;
381 apacket *get_apacket(void)
383 apacket *p = malloc(sizeof(apacket));
385 // free only being done to resolve SVACE issue.
387 fatal("failed to allocate an apacket");
389 memset(p, 0, sizeof(apacket) - MAX_PAYLOAD);
390 set_insert((void*)p);
394 void put_apacket(apacket *p)
396 int result = access((const char *) p, F_OK);
397 if ((result == -1) && (errno == EFAULT)) {
398 E("Invalid apacket = [0x%p]", p);
399 fatal("Invalid apacket = [0x%p]", p);
401 if(set_find((void*)p) == 1)
405 D("Memory Free done for [0x%p]", p);
411 D("Memory Free not done for [0x%p] as not available in set", p);
415 void handle_online(void)
420 void handle_offline(atransport *t)
423 //Close the associated usb
424 run_transport_disconnects(t);
429 void print_packet(const char *label, apacket *p)
435 switch(p->msg.command){
436 case A_SYNC: tag = "SYNC"; break;
437 case A_CNXN: tag = "CNXN" ; break;
438 case A_OPEN: tag = "OPEN"; break;
439 case A_OKAY: tag = "OKAY"; break;
440 case A_CLSE: tag = "CLSE"; break;
441 case A_WRTE: tag = "WRTE"; break;
442 default: tag = "????"; break;
445 fprintf(stderr, "%s: %s %08x %08x %04x \"",
446 label, tag, p->msg.arg0, p->msg.arg1, p->msg.data_length);
447 count = p->msg.data_length;
449 if(count > DUMPMAX) {
456 if((*x >= ' ') && (*x < 127)) {
463 fprintf(stderr, tag);
467 #ifdef SUPPORT_ENCRYPT
469 desc. : 암호화 실패 메시지 전송
470 parameter : [in] apacket* p : sdbd로 들어온 메시지
471 [in] atransport *t : 현재 연결에 대한 atransport
472 [in] unsigned failed_value : 실패 값
474 void send_encr_fail(apacket* p, atransport *t, unsigned failed_value){
476 enc_p = get_apacket();
477 enc_p->msg.command = A_ENCR; // 암호화 메시지
478 enc_p->msg.arg0 = failed_value; // 실패값
479 enc_p->msg.arg1 = p->msg.arg1;
480 send_packet(enc_p, t);
481 //put_apacket(enc_p);
486 parameter : [in] apacket* p : sdbd로 들어온 메시지
487 [in/out] atransport *t : 현재 연결에 대한 atransport
488 ret : 0 : 정상적으로 메시지 전송
491 int handle_encr_packet(apacket* p, atransport *t){
492 static int sessionID = 0;
494 apacket* enc_p = NULL;
496 if(p->msg.arg0 == ENCR_SET_ON_REQ){ // hello 메시지인 경우
497 t->sessionID = sessionID;
498 if((retVal = security_init(t->sessionID, NULL)) == 1){ // 암호화 handshaking을 위한 init
499 if(security_parse_server_hello(t->sessionID, p) == 1){ // hello 메시지 파싱
500 I("security_parse_server_hello success\n");
501 enc_p = get_apacket();
502 if(security_gen_client_hello(t->sessionID, enc_p) == 1){ // hello 메시지 생성
503 I("security_gen_client_hello success\n");
504 enc_p->msg.command = A_ENCR;
505 enc_p->msg.arg0 = ENCR_SET_ON_REQ;
506 enc_p->msg.arg1 = p->msg.arg1;
508 send_packet(enc_p, t);
510 else { // hello 메시지 생성 실패
511 E("security_gen_client_hello error\n");
512 send_encr_fail(p, t, ENCR_ON_FAIL); // 암호화 on 실패 메시지 전송
513 t->encryption = ENCR_OFF; // 암호화 모드는 off
514 security_deinit(t->sessionID);
518 else{ // hello 메시지 파싱 실패
519 E("security_parse_server_hello error\n");
520 send_encr_fail(p, t, ENCR_ON_FAIL);
521 t->encryption = ENCR_OFF;
522 security_deinit(t->sessionID);
527 E("security_init error\n");
528 send_encr_fail(p, t, ENCR_ON_FAIL);
529 t->encryption = ENCR_OFF;
532 security_deinit(t->sessionID);
534 //here!! do security_deinit(), but when plugin pointer is null -> not deinit
538 else if(p->msg.arg0 == ENCR_SET_ON_OK){ // ack 메시지인 경우
539 if(security_parse_server_ack(t->sessionID, p) == 1){ // ack 메시지 파싱
540 enc_p = get_apacket();
541 if(security_gen_client_ack(t->sessionID, enc_p) == 1){ // ack 메시지 생성
542 I("security_gen_client_ack success\n");
543 enc_p->msg.command = A_ENCR;
544 enc_p->msg.arg0 = ENCR_SET_ON_OK;
545 enc_p->msg.arg1 = p->msg.arg1;
546 t->encryption = ENCR_ON;
547 send_packet(enc_p, t);
549 else { // ack 메시지 생성에 실패한 경우
550 E("security_gen_client_ack error\n");
551 send_encr_fail(p, t, ENCR_ON_FAIL);
552 t->encryption = ENCR_OFF;
553 security_deinit(t->sessionID);
557 else { // ack 메시지 파싱에 실패한 경우
558 E("security_parse_server_ack error\n");
559 send_encr_fail(p, t, ENCR_ON_FAIL);
560 t->encryption = ENCR_OFF;
561 security_deinit(t->sessionID);
565 else if(p->msg.arg0 == ENCR_SET_OFF){ // 암호화 모드 off 요청 메시지
566 if(t->encryption == ENCR_ON && security_deinit(t->sessionID) == 1){ // 현재 암호화 모드가 on 상태인 경우
567 enc_p = get_apacket();
568 t->encryption = ENCR_OFF; // 현재 연결에 대한 암호화 모드 off
569 enc_p->msg.command = A_ENCR;
570 enc_p->msg.arg0 = ENCR_SET_OFF;
571 enc_p->msg.arg1 = p->msg.arg1;
572 send_packet(enc_p, t);
574 else { // 암호화 모드 off에 실패한 경우
575 E("security_deinit error\n");
576 send_encr_fail(p, t, ENCR_OFF_FAIL); // 암호화 모드 off 실패 메시지 전송
580 else if(p->msg.arg0 == ENCR_GET){ // 암호화 모드의 상태 요청 메시지인 경우
581 enc_p = get_apacket();
582 enc_p->msg.command = A_ENCR;
583 enc_p->msg.arg0 = ENCR_GET; // 암호화 모드 status get메시지
584 enc_p->msg.arg1 = p->msg.arg1;
585 if(t->encryption == ENCR_ON){ // 암호화 모드가 on인 경우
586 enc_p->msg.data_length = 13;
587 strncpy((char*)enc_p->data, "encryption:on", enc_p->msg.data_length + 1); // encryption:on 메시지 전송
588 } else if(t->encryption == ENCR_OFF){ // 암호화 모드가 off인 경우
589 enc_p->msg.data_length = 14;
590 strncpy((char*)enc_p->data, "encryption:off", enc_p->msg.data_length + 1); // encryption:off 메시지 전송
592 send_packet(enc_p, t);
594 else if (p->msg.arg0 == ENCR_ON_FAIL) // 암호화 모드를 on 하는 도중 실패한 경우 받는 메시지
596 t->encryption = ENCR_OFF; // 암호화 모드를 다시 off
597 E("encryption on failed\n");
599 else if (p->msg.arg0 == ENCR_OFF_FAIL) // 암호화 모드를 off하는 도중 실패한 경우 받는 메시지
601 //t->encryption = ENCR_ON;
602 E("encryption off failed\n");
604 //put_apacket(enc_p);
611 static void send_ready(unsigned local, unsigned remote, atransport *t)
613 I("Calling send_ready \n");
614 apacket *p = get_apacket();
615 D("Memory allocated for packet at [0x%p]", p);
616 p->msg.command = A_OKAY;
618 p->msg.arg1 = remote;
622 static void send_close(unsigned local, unsigned remote, atransport *t)
624 I("Calling send_close \n");
625 apacket *p = get_apacket();
626 D("Memory allocated for packet at [0x%p]", p);
627 p->msg.command = A_CLSE;
629 p->msg.arg1 = remote;
633 static void send_connect(atransport *t)
635 I("Calling send_connect \n");
636 apacket *cp = get_apacket();
637 D("Memory allocated for packet at [0x%p]", cp);
638 cp->msg.command = A_CNXN;
639 cp->msg.arg0 = A_VERSION;
640 #ifdef SUPPORT_ENCRYPT
641 cp->msg.arg1 = MAX_PAYLOAD - 100; // connection 시, sdb server의 패킷 크기를 암호화 오버로드 만큼 줄임
643 cp->msg.arg1 = MAX_PAYLOAD;
645 char device_name[256]={0,};
648 if (request_lock_state_to_plugin(LOCKTYPE_PASSWORD) == 1) {
650 t->connection_state = CS_PWLOCK;
654 r = get_emulator_name(device_name, sizeof device_name);
656 r = get_device_name(device_name, sizeof device_name);
659 snprintf((char*) cp->data, sizeof cp->data, "%s::%s::%d", sdb_device_banner, DEFAULT_DEVICENAME, status);
661 snprintf((char*) cp->data, sizeof cp->data, "%s::%s::%d", sdb_device_banner, device_name, status);
664 if (extcmd != NULL) {
665 char extbuf[BUF_SIZE] = {0,};
666 snprintf(extbuf, sizeof extbuf, "::%s", extcmd);
667 strncat((char*) cp->data, extbuf, sizeof(cp->data) - strlen((const char*)cp->data)- 1);
669 cp->msg.data_length = strlen((char*) cp->data) + 1;
670 D("CNXN data: %s\n", (char*)cp->data);
675 void send_device_status()
677 I("broadcast device status\n");
678 apacket* cp = get_apacket();
679 D("Memory allocated for packet at [0x%p]", cp);
680 cp->msg.command = A_STAT;
681 cp->msg.arg0 = is_pwlocked;
684 broadcast_transport(cp);
686 //all broadcasted packets are memory copied
687 //so, we should call put_apacket
688 D("Memory trying to be being Freed for packet at [0x%p]", cp);
692 static char *connection_state_name(atransport *t)
698 switch(t->connection_state) {
710 static int get_str_cmdline(char *src, char *dest, char str[], int str_size) {
711 char *s = strstr(src, dest);
715 char *e = strstr(s, " ");
720 int len = e-s-strlen(dest);
722 if (len >= str_size) {
723 E("buffer size(%d) should be bigger than %d\n", str_size, len+1);
727 strncpy(str, s + strlen(dest), len);
732 int get_emulator_forward_port() {
733 SdbdCommandlineArgs *sdbd_args = &sdbd_commandline_args; /* alias */
735 if (sdbd_args->emulator.host == NULL) {
739 return sdbd_args->emulator.port;
742 int get_emulator_name(char str[], int str_size) {
743 SdbdCommandlineArgs *sdbd_args = &sdbd_commandline_args; /* alias */
745 if (sdbd_args->emulator.host == NULL) {
749 s_strncpy(str, sdbd_args->emulator.host, str_size);
753 int get_device_name(char str[], int str_size) {
755 int r = system_info_get_platform_string("http://tizen.org/system/model_name", &value);
756 if (r != SYSTEM_INFO_ERROR_NONE) {
757 E("fail to get system model:%d\n", errno);
760 s_strncpy(str, value, str_size);
761 D("returns model_name:%s\n", value);
768 int fd = unix_open(USB_SERIAL_PATH, O_RDONLY);
770 D("fail to read:%s (%d)\n", USB_SERIAL_PATH, errno);
774 if(read_line(fd, str, str_size)) {
775 D("device serial name: %s\n", str);
784 static int get_cmdline_value(char *split, char str[], int str_size) {
786 int fd = unix_open(PROC_CMDLINE_PATH, O_RDONLY);
789 E("fail to read /proc/cmdline\n");
792 if(read_line(fd, cmdline, sizeof(cmdline))) {
793 D("qemu cmd: %s\n", cmdline);
794 if (get_str_cmdline(cmdline, split, str, str_size) < 1) {
795 E("could not get the (%s) value from cmdline\n", split);
804 int get_emulator_hostip(char str[], int str_size) {
805 return get_cmdline_value("host_ip=", str, str_size);
808 int get_emulator_guestip(char str[], int str_size) {
811 struct sockaddr_in *sin;
813 s = socket(AF_INET, SOCK_DGRAM, 0);
819 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", GUEST_IP_INTERFACE);
820 if(ioctl(s, SIOCGIFHWADDR, &ifr) < 0) {
821 E("ioctl hwaddr error\n");
826 if(ioctl(s, SIOCGIFADDR, &ifr) < 0) {
827 E("ioctl addr error\n");
831 sin = (struct sockaddr_in *)&ifr.ifr_addr;
832 snprintf(str, str_size, "%s", inet_ntoa(sin->sin_addr));
838 void parse_banner(char *banner, atransport *t)
840 char *type, *product, *end;
842 D("parse_banner: %s\n", banner);
844 product = strchr(type, ':');
851 /* remove trailing ':' */
852 end = strchr(product, ':');
855 /* save product name in device structure */
856 if (t->product == NULL) {
857 t->product = strdup(product);
858 } else if (strcmp(product, t->product) != 0) {
860 t->product = strdup(product);
863 if(!strcmp(type, "bootloader")){
864 I("setting connection_state to CS_BOOTLOADER\n");
865 t->connection_state = CS_BOOTLOADER;
870 if(!strcmp(type, "device")) {
871 I("setting connection_state to CS_DEVICE\n");
872 t->connection_state = CS_DEVICE;
877 if(!strcmp(type, "recovery")) {
878 I("setting connection_state to CS_RECOVERY\n");
879 t->connection_state = CS_RECOVERY;
884 if(!strcmp(type, "sideload")) {
885 I("setting connection_state to CS_SIDELOAD\n");
886 t->connection_state = CS_SIDELOAD;
891 t->connection_state = CS_HOST;
894 static void update_version(atransport *t, int version, size_t payload)
896 #ifdef SUPPORT_ENCRYPT
897 size_t max_payload = MAX_PAYLOAD - 100;
899 size_t max_payload = MAX_PAYLOAD;
901 t->protocol_version = min(version, A_VERSION);
902 t->max_payload = min(payload, max_payload);
903 D("update transport version. version=%x, max_payload=%zu\n", t->protocol_version, t->max_payload);
906 void handle_packet(apacket *p, atransport *t)
909 int result = access((const char *) p, F_OK);
910 if ((result == -1) && (errno == EFAULT)) {
911 fatal("Invalid apacket = [0x%p]", p);
916 // D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0],
917 // ((char*) (&(p->msg.command)))[1],
918 // ((char*) (&(p->msg.command)))[2],
919 // ((char*) (&(p->msg.command)))[3]);
921 print_packet("recv", p);
923 switch(p->msg.command){
927 if(HOST) send_connect(t);
929 t->connection_state = CS_OFFLINE;
935 case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */
936 /* XXX verify version, etc */
937 if(t->connection_state != CS_OFFLINE) {
938 t->connection_state = CS_OFFLINE;
941 update_version(t, p->msg.arg0, p->msg.arg1);
942 parse_banner((char*) p->data, t);
944 if(!HOST) send_connect(t);
947 case A_OPEN: /* OPEN(local-id, 0, "destination") */
948 if (request_lock_state_to_plugin(LOCKTYPE_PASSWORD) == 1 && t->connection_state == CS_PWLOCK) {
949 // in case of already locked before get A_CNXN
950 E("open failed due to password locked before get A_CNXN:%d\n", t->connection_state);
951 send_close(0, p->msg.arg0, t);
953 if(t->connection_state != CS_OFFLINE) {
954 char *name = (char*) p->data;
955 name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0;
956 s = create_local_service_socket(name);
958 send_close(0, p->msg.arg0, t);
960 s->peer = create_remote_socket(p->msg.arg0, t);
962 send_ready(s->id, s->peer->id, t);
969 case A_OKAY: /* READY(local-id, remote-id, "") */
970 if(t->connection_state != CS_OFFLINE) {
971 if((s = find_local_socket(p->msg.arg1))) {
973 s->peer = create_remote_socket(p->msg.arg0, t);
981 case A_CLSE: /* CLOSE(local-id, remote-id, "") */
982 if(t->connection_state != CS_OFFLINE) {
983 if((s = find_local_socket(p->msg.arg1))) {
990 if(t->connection_state != CS_OFFLINE) {
991 if((s = find_local_socket(p->msg.arg1))) {
992 unsigned rid = p->msg.arg0;
993 p->len = p->msg.data_length;
995 if(s->enqueue(s, p) == 0) {
996 I("Enqueue the socket\n");
997 send_ready(s->id, rid, t);
1003 #ifdef SUPPORT_ENCRYPT
1004 case A_ENCR: // 암호화 메시지인 경우
1005 if(t->connection_state != CS_OFFLINE) {
1006 handle_encr_packet(p, t);
1012 printf("handle_packet: what is %08x?!\n", p->msg.command);
1014 D("Memory trying to be being Freed for packet at [0x%p]", p);
1018 alistener listener_list = {
1019 .next = &listener_list,
1020 .prev = &listener_list,
1023 static void ss_listener_event_func(int _fd, unsigned ev, void *_l)
1029 struct sockaddr addr;
1033 alen = sizeof(addr);
1034 fd = sdb_socket_accept(_fd, &addr, &alen);
1037 ret = sdb_socket_setbufsize(fd, CHUNK_SIZE);
1039 D("sdbd: sdb_socket_setbufsize failed (%d)\n", ret);
1042 s = create_local_socket(fd);
1044 connect_to_smartsocket(s);
1052 static void listener_event_func(int _fd, unsigned ev, void *_l)
1058 struct sockaddr addr;
1062 alen = sizeof(addr);
1063 fd = sdb_socket_accept(_fd, &addr, &alen);
1066 s = create_local_socket(fd);
1068 s->transport = l->transport;
1069 connect_to_remote(s, l->connect_to);
1077 static void free_listener(alistener* l)
1080 l->next->prev = l->prev;
1081 l->prev->next = l->next;
1082 l->next = l->prev = l;
1085 // closes the corresponding fd
1086 fdevent_remove(&l->fde);
1089 free((char*)l->local_name);
1092 free((char*)l->connect_to);
1095 remove_transport_disconnect(l->transport, &l->disconnect);
1100 static void listener_disconnect(void* _l, atransport* t)
1107 int local_name_to_fd(const char *name)
1111 if(!strncmp("tcp:", name, 4)){
1113 port = atoi(name + 4);
1114 ret = socket_loopback_server(port, SOCK_STREAM);
1117 #ifndef HAVE_WIN32_IPC /* no Unix-domain sockets on Win32 */
1118 // It's non-sensical to support the "reserved" space on the sdb host side
1119 if(!strncmp(name, "local:", 6)) {
1120 return socket_local_server(name + 6,
1121 ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
1122 } else if(!strncmp(name, "localabstract:", 14)) {
1123 return socket_local_server(name + 14,
1124 ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
1125 } else if(!strncmp(name, "localfilesystem:", 16)) {
1126 return socket_local_server(name + 16,
1127 ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
1131 printf("unknown local portname '%s'\n", name);
1135 static int remove_listener(const char *local_name, const char *connect_to, atransport* transport)
1139 for (l = listener_list.next; l != &listener_list; l = l->next) {
1140 if (!strcmp(local_name, l->local_name) &&
1141 !strcmp(connect_to, l->connect_to) &&
1142 l->transport && l->transport == transport) {
1144 listener_disconnect(l, transport);
1152 static int install_listener(const char *local_name, const char *connect_to, atransport* transport)
1156 //printf("install_listener('%s','%s')\n", local_name, connect_to);
1158 for(l = listener_list.next; l != &listener_list; l = l->next){
1159 if(strcmp(local_name, l->local_name) == 0) {
1162 /* can't repurpose a smartsocket */
1163 if(l->connect_to[0] == '*') {
1167 cto = strdup(connect_to);
1172 //printf("rebinding '%s' to '%s'\n", local_name, connect_to);
1173 free((void*) l->connect_to);
1174 l->connect_to = cto;
1175 if (l->transport != transport) {
1176 remove_transport_disconnect(l->transport, &l->disconnect);
1177 l->transport = transport;
1178 add_transport_disconnect(l->transport, &l->disconnect);
1184 if((l = calloc(1, sizeof(alistener))) == 0) goto nomem;
1185 if((l->local_name = strdup(local_name)) == 0) goto nomem;
1186 if((l->connect_to = strdup(connect_to)) == 0) goto nomem;
1189 l->fd = local_name_to_fd(local_name);
1191 free((void*) l->local_name);
1192 free((void*) l->connect_to);
1194 printf("cannot bind '%s'\n", local_name);
1198 if (close_on_exec(l->fd) < 0) {
1199 E("fail to close fd exec:%d\n",l->fd);
1201 if(!strcmp(l->connect_to, "*smartsocket*")) {
1202 fdevent_install(&l->fde, l->fd, ss_listener_event_func, l);
1204 fdevent_install(&l->fde, l->fd, listener_event_func, l);
1206 fdevent_set(&l->fde, FDE_READ);
1208 l->next = &listener_list;
1209 l->prev = listener_list.prev;
1212 l->transport = transport;
1215 l->disconnect.opaque = l;
1216 l->disconnect.func = listener_disconnect;
1217 add_transport_disconnect(transport, &l->disconnect);
1222 fatal("cannot allocate listener");
1226 static void sdb_cleanup(void)
1228 clear_sdbd_commandline_args(&sdbd_commandline_args);
1230 if (is_support_usbproto()) {
1233 // if(required_pid > 0) {
1234 // kill(required_pid, SIGKILL);
1237 unload_sdbd_plugin();
1240 static void sdb_service_cleanup(void)
1242 if (exit_cleanup_required)
1244 unload_sdbd_service_plugin();
1249 void start_device_log(void)
1252 char path[2*PATH_MAX] = {0, };
1253 char path_folder[PATH_MAX] = {0, };
1254 char path_file[PATH_MAX] = {0, };
1258 // read the trace mask from persistent property persist.sdb.trace_mask
1259 // give up if the property is not set or cannot be parsed
1260 char* p_trace = get_sdb_log_conf("SDB_TRACE");
1261 if ((p_trace == NULL ) && !is_enable_sdbd_log()) {
1266 char* p_path = get_sdb_log_conf("SDBD_LOG_PATH");
1268 snprintf(path_folder, sizeof(path_folder), "%s", p_path);
1270 } else if (g_capabilities.log_path[0] != '\0') {
1271 snprintf(path_folder, sizeof(path_folder), "%s", g_capabilities.log_path);
1278 localtime_r(&t, &now);
1280 strftime(path_file, sizeof(path_file),
1281 "sdbd-%Y-%m-%d-%H-%M-%S.txt",
1284 snprintf(path, sizeof(path), "%s/%s", path_folder, path_file);
1286 fd = unix_open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
1291 // redirect stdout and stderr to the log file
1294 fprintf(stderr,"--- sdbd starting (pid %d) ---\n", getpid());
1297 fd = unix_open("/dev/null", O_RDONLY);
1299 // hopefully not gonna happen
1306 /* Constructs a local name of form tcp:port.
1307 * target_str points to the target string, it's content will be overwritten.
1308 * target_size is the capacity of the target string.
1309 * server_port is the port number to use for the local name.
1311 void build_local_name(char* target_str, size_t target_size, int server_port)
1313 snprintf(target_str, target_size, "tcp:%d", server_port);
1316 static void init_drop_privileges() {
1317 #ifdef _DROP_PRIVILEGE
1324 int should_drop_privileges() {
1325 if (rootshell_mode == 1) { // if root, then don't drop
1331 #include <gio/gio.h>
1333 #define BOOTING_DONE_PATH "/org/tizen/system"
1334 #define BOOTING_DONE_SIGNAL "BootingDone"
1335 #define BOOTING_DONE_INTERFACE "org.tizen.system.Booting"
1336 #define SDBD_BOOT_INFO_FILE "/tmp/sdbd_boot_info"
1338 static GMainLoop *g_mainloop;
1340 static void booting_done_signal_subscriber(GDBusConnection *connection,
1341 const gchar *sender, const gchar *path, const gchar *interface,
1342 const gchar *signal, GVariant *parameters, gpointer user_data)
1344 if (g_strcmp0(signal, BOOTING_DONE_SIGNAL) != 0) {
1345 D("received signal(%s) does not match the desired signal(%s)\n",
1346 signal, BOOTING_DONE_SIGNAL);
1350 D("received the \"%s\" signal\n", signal);
1353 if (access(SDBD_BOOT_INFO_FILE, F_OK) == 0) {
1354 I("booting is already done\n");
1356 FILE *info_file = fopen(SDBD_BOOT_INFO_FILE, "w");
1357 if (info_file != NULL) {
1358 char* tmppath = realpath(SDBD_BOOT_INFO_FILE, NULL);
1359 if (tmppath != NULL) {
1360 if (strcmp(SDBD_BOOT_INFO_FILE, tmppath) == 0) {
1361 fprintf(info_file, "%d", 1);
1362 I("booting is done\n");
1364 D("Path has symbolic link, security risk \n");
1370 D("Getting realpath failed\n");
1376 I("handled the booting done signal\n");
1377 g_main_loop_quit(g_mainloop);
1380 static void *bootdone_cb(void *args)
1382 GError *error = NULL;
1383 GDBusConnection *connection = NULL;
1386 connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
1387 if (connection == NULL) {
1388 if (error != NULL) {
1389 E("failed to connect to the system bus: %s\n", error->message);
1390 g_error_free(error);
1392 E("failed to connect to the system bus\n");
1397 g_mainloop = g_main_loop_new(NULL, false);
1398 if (g_mainloop == NULL) {
1399 E("failed to create a g_main_loop\n");
1403 id = g_dbus_connection_signal_subscribe(connection,
1404 NULL, BOOTING_DONE_INTERFACE, BOOTING_DONE_SIGNAL,
1405 BOOTING_DONE_PATH, NULL, G_DBUS_SIGNAL_FLAGS_NONE,
1406 booting_done_signal_subscriber, NULL, NULL);
1408 E("failed to subscribe to the booting done signal\n");
1412 I("wait for the booting done signal\n");
1413 g_main_loop_run(g_mainloop);
1415 g_dbus_connection_signal_unsubscribe(connection, id);
1418 if (g_mainloop != NULL) {
1419 g_main_loop_unref(g_mainloop);
1421 if (connection != NULL) {
1422 g_object_unref(connection);
1424 I("exit the bootdone_cb thread\n");
1429 void register_bootdone_cb()
1432 if (sdb_thread_create(&t, bootdone_cb, NULL)) {
1433 E("can not create a service thread to check the booting done\n");
1436 I("created the bootdone_cb thread\n");
1439 static int sdbd_set_groups(const char *name, int gid, struct group_info default_groups[], int default_groups_size) {
1440 gid_t *group_ids = NULL;
1443 int group_match = 0;
1444 int added_group_cnt = 0;
1446 if (getgrouplist(name, gid, NULL, &ngroups) == -1) {
1447 D("group list : ngroups = %d\n", ngroups);
1449 group_ids = malloc((ngroups + default_groups_size) * sizeof(gid_t));
1450 if (group_ids == NULL) {
1451 E("failed to allocate group_ids(%zu)\n", (ngroups + default_groups_size) * sizeof(gid_t));
1454 if (getgrouplist(name, gid, group_ids, &ngroups) == -1) {
1455 E("failed to getgrouplist(), ngroups = %d\n", ngroups);
1459 if(default_groups_size >= 1) {
1460 for (i = 0; default_groups[i].name != NULL; i++) {
1461 for (j = 0; j < ngroups; j++) {
1462 if (group_ids[j] == default_groups[i].gid) {
1467 if (group_match == 0 && default_groups[i].gid != -1) {
1468 group_ids[ngroups + added_group_cnt] = default_groups[i].gid;
1474 if (setgroups(ngroups+added_group_cnt, group_ids) != 0) {
1475 E("failed to setgroups().\n");
1484 static int sdbd_get_user_pwd(const char* user_name, struct passwd* pwd, char* buf, size_t bufsize) {
1485 struct passwd *result = NULL;
1488 ret = getpwnam_r(user_name, pwd, buf, bufsize, &result);
1489 if (result == NULL) {
1491 E("Not found passwd : username(%s)\n", user_name);
1494 E("failed to getpwnam_r\n");
1502 static int sdbd_get_group(const char* group_name, struct group* grp, char* buf, size_t bufsize) {
1503 struct group *result = NULL;
1506 ret = getgrnam_r(group_name, grp, buf, bufsize, &result);
1507 if (result == NULL) {
1509 E("Not found group : groupname(%s)\n", group_name);
1512 E("failed to getgrnam_r\n");
1520 int set_sdk_user_privileges(int is_drop_capability_after_fork) {
1521 if (!is_init_sdk_userinfo) {
1522 E("failed to init sdk user information.\n");
1527 * If a process switches its real, effective, or saved uids from at least one being 0 to all being non-zero,
1528 * then both the permitted and effective capabilities are cleared.
1530 if(is_drop_capability_after_fork) {
1532 if (setuid(g_root_user_id) != 0) {
1533 E("set root user id failed (errno: %d)\n", errno);
1538 if (sdbd_set_groups(SDK_USER_NAME, g_sdk_group_id, g_default_groups, SDB_DEFAULT_GROUPS_CNT) < 0) {
1539 E("set groups failed (errno: %d)\n", errno);
1543 if (setgid(g_sdk_group_id) != 0) {
1544 E("set group id failed (errno: %d)\n", errno);
1548 if (setuid(g_sdk_user_id) != 0) {
1549 E("set user id failed (errno: %d)\n", errno);
1551 // if(is_drop_capability_after_fork) {
1556 if (chdir(g_sdk_home_dir) < 0) {
1557 E("unable to change working directory to %s\n", g_sdk_home_dir);
1560 // TODO: use pam later
1561 if (g_sdk_home_dir_env) {
1562 putenv(g_sdk_home_dir_env);
1568 int set_root_privileges() {
1570 if (sdbd_set_groups(ROOT_USER_NAME, g_root_group_id, NULL, 0) < 0) {
1571 E("set root groups failed (errno: %d)\n", errno);
1574 if (setgid(g_root_group_id) != 0) {
1575 E("set root group id failed (errno: %d)\n", errno);
1578 if (setuid(g_root_user_id) != 0) {
1579 E("set root user id failed (errno: %d)\n", errno);
1582 if (chdir(g_root_home_dir) < 0) {
1583 E("unable to change root working directory to %s\n", g_sdk_home_dir);
1586 // TODO: use pam later
1587 if (g_root_home_dir_env) {
1588 putenv(g_root_home_dir_env);
1594 #define SDB_PW_GR_DEFAULT_SIZE (16*1024)
1595 static long get_passwd_bufsize() {
1598 bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
1600 bufsize = SDB_PW_GR_DEFAULT_SIZE;
1606 static long get_group_bufsize() {
1609 bufsize = sysconf(_SC_GETGR_R_SIZE_MAX);
1611 bufsize = SDB_PW_GR_DEFAULT_SIZE;
1617 static int init_sdb_default_groups() {
1623 bufsize = get_group_bufsize();
1624 buf = malloc(bufsize);
1626 E("failed to allocate gruop buf(%ld)\n", bufsize);
1630 for (i = 0; g_default_groups[i].name != NULL; i++) {
1631 memset(buf, 0, bufsize);
1632 if (sdbd_get_group(g_default_groups[i].name, &grp, buf, bufsize) == 0) {
1633 g_default_groups[i].gid = grp.gr_gid;
1635 E("failed get group info.(errno: %d)\n", errno);
1643 static void set_static_root_userinfo() {
1644 g_root_user_id = STATIC_ROOT_USER_ID;
1645 g_root_group_id = STATIC_ROOT_GROUP_ID;
1646 g_root_home_dir = STATIC_ROOT_HOME_DIR;
1649 static void set_static_sdk_userinfo() {
1650 g_sdk_user_id = STATIC_SDK_USER_ID;
1651 g_sdk_group_id = STATIC_SDK_GROUP_ID;
1652 g_sdk_home_dir = STATIC_SDK_HOME_DIR;
1655 static int init_root_userinfo() {
1660 bufsize = get_passwd_bufsize();
1661 buf = malloc(bufsize);
1663 E("failed to allocate passwd buf(%ld)\n", bufsize);
1664 set_static_root_userinfo();
1666 if (sdbd_get_user_pwd(ROOT_USER_NAME, &pwd, buf, bufsize) < 0) {
1667 E("failed to get root user passwd info.(errno: %d)\n", errno);
1668 set_static_root_userinfo();
1670 D("username=%s, uid=%d, gid=%d, dir=%s\n", pwd.pw_name, pwd.pw_uid, pwd.pw_gid, pwd.pw_dir);
1672 g_root_user_id = pwd.pw_uid;
1673 g_root_group_id = pwd.pw_gid;
1674 g_root_home_dir = strdup(pwd.pw_dir);
1679 int env_size = strlen("HOME=") + strlen(g_root_home_dir) + 1;
1680 g_root_home_dir_env = malloc(env_size);
1681 if(g_root_home_dir_env == NULL) {
1682 E("failed to allocate for home dir env string\n");
1684 snprintf(g_root_home_dir_env, env_size, "HOME=%s", g_root_home_dir);
1690 static int init_sdk_userinfo() {
1695 if (is_init_sdk_userinfo) {
1699 if (init_sdb_default_groups() < 0) {
1700 E("failed to initialize default groups.\n");
1703 bufsize = get_passwd_bufsize();
1704 buf = malloc(bufsize);
1706 E("failed to allocate passwd buf(%ld)\n", bufsize);
1707 set_static_sdk_userinfo();
1709 if (sdbd_get_user_pwd(SDK_USER_NAME, &pwd, buf, bufsize) < 0) {
1710 E("get user passwd info.(errno: %d)\n", errno);
1711 set_static_sdk_userinfo();
1713 D("username=%s, uid=%d, gid=%d, dir=%s\n", pwd.pw_name, pwd.pw_uid, pwd.pw_gid, pwd.pw_dir);
1715 g_sdk_user_id = pwd.pw_uid;
1716 g_sdk_group_id = pwd.pw_gid;
1717 g_sdk_home_dir = strdup(pwd.pw_dir);
1722 int env_size = strlen("HOME=") + strlen(g_sdk_home_dir) + 1;
1723 g_sdk_home_dir_env = malloc(env_size);
1724 if(g_sdk_home_dir_env == NULL) {
1725 E("failed to allocate for home dir env string\n");
1727 snprintf(g_sdk_home_dir_env, env_size, "HOME=%s", g_sdk_home_dir);
1730 is_init_sdk_userinfo = 1;
1735 static int safe_system(char *cmd, char *argv[], char *envp[]) {
1744 execve(cmd, argv, envp);
1745 E("- exec '%s' failed: (errno:%d) -\n", cmd, errno);
1749 pid_t p = waitpid(pid, &status, 0);
1759 static void init_sdk_requirements() {
1760 // set env variable for temporary
1761 // TODO: should use pam instead later!!
1762 putenv("TERM=linux");
1763 putenv("HOME=/root");
1765 init_sdk_userinfo();
1766 init_root_userinfo();
1768 if (is_emulator()) {
1769 register_bootdone_cb();
1773 static void init_capabilities(void) {
1777 memset(&g_capabilities, 0, sizeof(g_capabilities));
1779 // architecture support
1780 char* arch = get_platfrom_architecture();
1781 snprintf(g_capabilities.architecture, sizeof(g_capabilities.architecture),
1784 // CPU Architecture of model
1785 ret = system_info_get_platform_string("http://tizen.org/feature/platform.core.cpu.arch", &value);
1786 if (ret != SYSTEM_INFO_ERROR_NONE) {
1787 snprintf(g_capabilities.cpu_arch, sizeof(g_capabilities.cpu_arch),
1789 E("fail to get the CPU architecture of model:%d\n", errno);
1791 if (value != NULL) {
1792 // check for armv8 and 32 bit architecture, for it make the cpu arch as armv7l
1793 if(!strncmp(value,"armv8",sizeof("armv8")+1) && !strncmp(arch,"32",sizeof("32")+1))
1795 D("Changing cpu arch in capability from %s to %s for %s bit\n",value,"armv7l",arch);
1796 snprintf(g_capabilities.cpu_arch, sizeof(g_capabilities.cpu_arch),
1799 snprintf(g_capabilities.cpu_arch, sizeof(g_capabilities.cpu_arch),
1807 // Secure protocol support
1808 if(!request_capability_to_plugin(CAPABILITY_SECURE, g_capabilities.secure_protocol,
1809 sizeof(g_capabilities.secure_protocol))) {
1810 E("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_SECURE);
1811 snprintf(g_capabilities.secure_protocol, sizeof(g_capabilities.secure_protocol),
1816 // Interactive shell support
1817 if(!request_capability_to_plugin(CAPABILITY_INTER_SHELL, g_capabilities.intershell_support,
1818 sizeof(g_capabilities.intershell_support))) {
1819 E("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_INTER_SHELL);
1820 snprintf(g_capabilities.intershell_support, sizeof(g_capabilities.intershell_support),
1825 // File push/pull support
1826 if(!request_capability_to_plugin(CAPABILITY_FILESYNC, g_capabilities.filesync_support,
1827 sizeof(g_capabilities.filesync_support))) {
1828 E("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_FILESYNC);
1829 snprintf(g_capabilities.filesync_support, sizeof(g_capabilities.filesync_support),
1834 // USB protocol support
1835 if(!request_capability_to_plugin(CAPABILITY_USB_PROTOCOL, g_capabilities.usbproto_support,
1836 sizeof(g_capabilities.usbproto_support))) {
1837 E("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_USB_PROTOCOL);
1838 snprintf(g_capabilities.usbproto_support, sizeof(g_capabilities.usbproto_support),
1843 // Socket protocol support
1844 if(!request_capability_to_plugin(CAPABILITY_SOCK_PROTOCOL, g_capabilities.sockproto_support,
1845 sizeof(g_capabilities.sockproto_support))) {
1846 E("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_SOCK_PROTOCOL);
1847 snprintf(g_capabilities.sockproto_support, sizeof(g_capabilities.sockproto_support),
1851 // Sdbd root permission
1852 snprintf(g_capabilities.root_permission, sizeof(g_capabilities.root_permission),
1855 // Root command support
1856 if(!request_capability_to_plugin(CAPABILITY_ROOT_ONOFF, g_capabilities.rootonoff_support,
1857 sizeof(g_capabilities.rootonoff_support))) {
1858 E("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_ROOT_ONOFF);
1859 snprintf(g_capabilities.rootonoff_support, sizeof(g_capabilities.rootonoff_support),
1864 // Encryption support
1865 if(!request_capability_to_plugin(CAPABILITY_ENCRYPTION, g_capabilities.encryption_support,
1866 sizeof(g_capabilities.encryption_support))) {
1867 E("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_ENCRYPTION);
1868 snprintf(g_capabilities.encryption_support, sizeof(g_capabilities.encryption_support),
1874 ret = is_container_enabled();
1875 snprintf(g_capabilities.zone_support, sizeof(g_capabilities.zone_support),
1876 "%s", ret == 1 ? ENABLED : DISABLED);
1878 // Multi-User support
1879 // XXX: There is no clear way to determine whether multi-user support.
1880 // Since TZ_SYS_DEFAULT_USER is set to "owner" for multi-user support,
1881 // guess whether multiuser support through that information.
1882 const char* sys_default_user = tzplatform_getenv(TZ_SYS_DEFAULT_USER);
1883 if (sys_default_user != NULL && !strcmp(sys_default_user, "owner")) {
1884 snprintf(g_capabilities.multiuser_support, sizeof(g_capabilities.multiuser_support),
1887 snprintf(g_capabilities.multiuser_support, sizeof(g_capabilities.multiuser_support),
1891 // Window size synchronization support
1892 snprintf(g_capabilities.syncwinsz_support, sizeof(g_capabilities.syncwinsz_support),
1896 if (SDK_TOOL_PATH == NULL) {
1897 E("fail to get SDK tool path.\n");
1898 snprintf(g_capabilities.sdk_toolpath, sizeof(g_capabilities.sdk_toolpath),
1901 snprintf(g_capabilities.sdk_toolpath, sizeof(g_capabilities.sdk_toolpath),
1902 "%s", SDK_TOOL_PATH);
1906 ret = system_info_get_platform_string("http://tizen.org/feature/profile", &value);
1907 if (ret != SYSTEM_INFO_ERROR_NONE) {
1908 snprintf(g_capabilities.profile_name, sizeof(g_capabilities.profile_name),
1910 E("fail to get profile name:%d\n", errno);
1912 snprintf(g_capabilities.profile_name, sizeof(g_capabilities.profile_name),
1914 if (value != NULL) {
1921 ret = system_info_get_platform_string("http://tizen.org/system/manufacturer", &value);
1922 if (ret != SYSTEM_INFO_ERROR_NONE) {
1923 snprintf(g_capabilities.vendor_name, sizeof(g_capabilities.vendor_name),
1925 E("fail to get the Vendor name:%d\n", errno);
1927 snprintf(g_capabilities.vendor_name, sizeof(g_capabilities.vendor_name),
1929 if (value != NULL) {
1935 // Target name of the launch possible
1936 if(!request_capability_to_plugin(CAPABILITY_CAN_LAUNCH, g_capabilities.can_launch,
1937 sizeof(g_capabilities.can_launch))) {
1938 E("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_CAN_LAUNCH);
1939 snprintf(g_capabilities.can_launch, sizeof(g_capabilities.can_launch),
1945 value = vconf_get_str(VCONFKEY_SETAPPL_DEVICE_NAME_STR);
1947 snprintf(g_capabilities.device_name, sizeof(g_capabilities.device_name),
1949 if (value != NULL) {
1953 snprintf(g_capabilities.device_name, sizeof(g_capabilities.device_name),
1955 E("fail to get the Device name:%d\n", errno);
1960 ret = system_info_get_platform_string("http://tizen.org/feature/platform.version", &value);
1961 if (ret != SYSTEM_INFO_ERROR_NONE) {
1962 snprintf(g_capabilities.platform_version, sizeof(g_capabilities.platform_version),
1964 E("fail to get platform version:%d\n", errno);
1966 snprintf(g_capabilities.platform_version, sizeof(g_capabilities.platform_version),
1968 if (value != NULL) {
1975 if(!request_capability_to_plugin(CAPABILITY_PRODUCT_VER, g_capabilities.product_version,
1976 sizeof(g_capabilities.product_version))) {
1977 E("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_PRODUCT_VER);
1978 snprintf(g_capabilities.product_version, sizeof(g_capabilities.product_version),
1984 snprintf(g_capabilities.sdbd_version, sizeof(g_capabilities.sdbd_version),
1985 "%d.%d.%d", SDB_VERSION_MAJOR, SDB_VERSION_MINOR, SDB_VERSION_PATCH);
1988 // Sdbd plugin version
1989 if(!request_capability_to_plugin(CAPABILITY_PLUGIN_VER, g_capabilities.sdbd_plugin_version,
1990 sizeof(g_capabilities.sdbd_plugin_version))) {
1991 E("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_PLUGIN_VER);
1992 snprintf(g_capabilities.sdbd_plugin_version, sizeof(g_capabilities.sdbd_plugin_version),
1998 if(!request_capability_to_plugin(CAPABILITY_LOG_ENABLE, g_capabilities.log_enable,
1999 sizeof(g_capabilities.log_enable))) {
2000 E("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_LOG_ENABLE);
2001 snprintf(g_capabilities.log_enable, sizeof(g_capabilities.log_enable),
2006 if(!request_capability_to_plugin(CAPABILITY_LOG_PATH, g_capabilities.log_path,
2007 sizeof(g_capabilities.log_path))) {
2008 E("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_LOG_PATH);
2009 snprintf(g_capabilities.log_path, sizeof(g_capabilities.log_path),
2013 // Application command support
2014 if(!request_capability_to_plugin(CAPABILITY_APPCMD, g_capabilities.appcmd_support,
2015 sizeof(g_capabilities.appcmd_support))) {
2016 E("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_APPCMD);
2017 snprintf(g_capabilities.appcmd_support, sizeof(g_capabilities.appcmd_support),
2021 // appid2pid support
2022 ret = is_appid2pid_supported();
2023 snprintf(g_capabilities.appid2pid_support, sizeof(g_capabilities.appid2pid_support),
2024 "%s", ret == 1 ? ENABLED : DISABLED);
2026 // pkgcmd debug mode support
2027 if(!request_capability_to_plugin(CAPABILITY_DEBUGMODE, g_capabilities.pkgcmd_debugmode,
2028 sizeof(g_capabilities.pkgcmd_debugmode))) {
2029 E("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_DEBUGMODE);
2030 snprintf(g_capabilities.pkgcmd_debugmode, sizeof(g_capabilities.pkgcmd_debugmode),
2034 // netcore debugger support
2035 ret = is_netcoredbg_supported();
2036 snprintf(g_capabilities.netcoredbg_support, sizeof(g_capabilities.netcoredbg_support),
2037 "%s", ret == 1 ? ENABLED : DISABLED);
2039 // Capability version
2040 snprintf(g_capabilities.sdbd_cap_version, sizeof(g_capabilities.sdbd_cap_version),
2041 "%d.%d", SDBD_CAP_VERSION_MAJOR, SDBD_CAP_VERSION_MINOR);
2044 static int is_support_usbproto()
2046 return (!strncmp(g_capabilities.usbproto_support, PLUGIN_RET_ENABLED, strlen(PLUGIN_RET_ENABLED)+1));
2049 static int is_support_sockproto()
2051 return (!strncmp(g_capabilities.sockproto_support, PLUGIN_RET_ENABLED, strlen(PLUGIN_RET_ENABLED)+1));
2054 #define EMULATOR_MODEL_NAME "Emulator"
2055 static void check_emulator_or_device()
2057 char model_name[256]={0,};
2060 // Get the model name from model_config.xml
2061 ret = get_device_name(model_name, sizeof model_name);
2063 if(!strncmp(model_name, EMULATOR_MODEL_NAME, strlen("Emulator")+1)){
2065 I("This target type is Emulator\n");
2068 I("This target type is Device\n");
2072 E("failed to get the model name.\n");
2076 static void fork_prepare_handler(void)
2078 sdb_mutex_lock(&D_lock);
2081 static void fork_parent_handler(void)
2083 sdb_mutex_unlock(&D_lock);
2086 static void fork_child_handler(void)
2088 sdb_mutex_unlock(&D_lock);
2091 int sdb_main(int server_port)
2093 check_emulator_or_device();
2097 init_capabilities();
2100 //start_device_log();
2102 init_drop_privileges();
2103 init_sdk_requirements();
2104 if (!request_validity_to_plugin(PLUGIN_SYNC_CMD_VERIFY_LAUNCH, NULL)) {
2105 E("sdbd should be launched in develop mode.\n");
2111 pthread_atfork(fork_prepare_handler, fork_parent_handler, fork_child_handler);
2113 atexit(sdb_cleanup);
2114 #if defined(HAVE_FORKEXEC)
2115 // No SIGCHLD. Let the service subproc handle its children.
2116 signal(SIGPIPE, SIG_IGN);
2119 init_transport_registration();
2121 /* don't listen on a port (default 5037) if running in secure mode */
2122 /* don't run as root if we are running in secure mode */
2124 if (should_drop_privileges()) {
2126 struct __user_cap_header_struct header;
2127 struct __user_cap_data_struct cap;
2129 if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0) {
2132 /* add extra groups:
2133 ** SID_TTY to access /dev/ptmx
2135 gid_t groups[] = { SID_TTY, SID_APP_LOGGING, SID_SYS_LOGGING };
2136 if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) {
2139 /* then switch user and group to "developer" */
2140 if (setgid(GID_DEVELOPER) != 0) {
2141 fprintf(stderr, "set group id failed errno: %d\n", errno);
2144 if (setuid(SID_DEVELOPER) != 0) {
2145 fprintf(stderr, "set user id failed errno: %d\n", errno);
2149 /* set CAP_SYS_BOOT capability, so "sdb reboot" will succeed */
2150 header.version = _LINUX_CAPABILITY_VERSION;
2152 cap.effective = cap.permitted = (1 << CAP_SYS_BOOT);
2153 cap.inheritable = 0;
2154 capset(&header, &cap);
2156 I("Local port disabled\n");
2158 char local_name[30];
2159 build_local_name(local_name, sizeof(local_name), server_port);
2160 if(install_listener(local_name, "*smartsocket*", NULL)) {
2165 /* choose the usb gadget backend */
2166 if (access(USB_NODE_FILE, F_OK) == 0) {
2167 /* legacy kernel-based sdb gadget */
2168 usb_init = &linux_usb_init;
2169 usb_cleanup = &linux_usb_cleanup;
2170 usb_write = &linux_usb_write;
2171 usb_read = &linux_usb_read;
2172 usb_close = &linux_usb_close;
2173 usb_kick = &linux_usb_kick;
2175 /* functionfs based gadget */
2176 usb_init = &ffs_usb_init;
2177 usb_cleanup = &ffs_usb_cleanup;
2178 usb_write = &ffs_usb_write;
2179 usb_read = &ffs_usb_read;
2180 usb_close = &ffs_usb_close;
2181 usb_kick = &ffs_usb_kick;
2184 if (is_support_usbproto()) {
2188 if (is_support_sockproto()) {
2189 /* by default don't listen on local transport but
2190 * listen if suitable command line argument has been provided */
2191 if (sdbd_commandline_args.sdbd_port >= 0) {
2192 local_init(sdbd_commandline_args.sdbd_port);
2194 local_init(DEFAULT_SDB_LOCAL_TRANSPORT_PORT);
2198 #if 0 /* tizen specific */
2199 D("sdb_main(): pre init_jdwp()\n");
2201 D("sdb_main(): post init_jdwp()\n");
2204 sdb_notify_startup(0, "READY=1");
2206 I("Event loop starting\n");
2210 if (is_support_usbproto()) {
2217 void sdb_main_service()
2220 init_capabilities();
2221 init_sdk_requirements();
2222 atexit(sdb_service_cleanup);
2225 int copy_packet(apacket* dest, apacket* src) {
2228 E("dest packet is NULL\n");
2233 E("src packet is NULL\n");
2237 dest->next = src->next;
2238 dest->ptr = src->ptr;
2239 dest->len = src->len;
2241 int data_length = src->msg.data_length;
2242 if(data_length > MAX_PAYLOAD) {
2243 data_length = MAX_PAYLOAD;
2245 memcpy(&(dest->msg), &(src->msg), sizeof(amessage) + data_length);
2250 int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s)
2252 atransport *transport = NULL;
2255 if(!strcmp(service, "kill")) {
2256 fprintf(stderr,"sdb server killed by remote request\n");
2258 sdb_write(reply_fd, "OKAY", 4);
2259 if (is_support_usbproto()) {
2265 if(!strncmp(service,"forward:",8) || !strncmp(service,"killforward:",12)) {
2266 char *local, *remote, *err;
2268 atransport *transport;
2270 int createForward = strncmp(service,"kill",4);
2272 local = service + (createForward ? 8 : 12);
2273 remote = strchr(local,';');
2275 sendfailmsg(reply_fd, "malformed forward spec");
2280 if((local[0] == 0) || (remote[0] == 0) || (remote[0] == '*')){
2281 sendfailmsg(reply_fd, "malformed forward spec");
2285 transport = acquire_one_transport(CS_ANY, ttype, serial, &err);
2287 sendfailmsg(reply_fd, err);
2291 if (createForward) {
2292 r = install_listener(local, remote, transport);
2294 r = remove_listener(local, remote, transport);
2297 /* 1st OKAY is connect, 2nd OKAY is status */
2298 writex(reply_fd, "OKAYOKAY", 8);
2302 if (createForward) {
2303 sendfailmsg(reply_fd, (r == -1) ? "cannot rebind smartsocket" : "cannot bind socket");
2305 sendfailmsg(reply_fd, "cannot remove listener");
2310 if(!strncmp(service,"get-state",strlen("get-state"))) {
2311 transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
2312 char *state = connection_state_name(transport);
2313 snprintf(buf, sizeof buf, "OKAY%04x%s",(unsigned)strlen(state),state);
2314 writex(reply_fd, buf, strlen(buf));