Merge "Fix for svace issues" into tizen
[sdk/target/sdbd.git] / src / sdb.c
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
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_SDB
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 #include <signal.h>
28 #include <grp.h>
29 #include <pwd.h>
30 #include <netdb.h>
31 #include <tzplatform_config.h>
32 #include <pthread.h>
33 #include <dlfcn.h>
34 #include <sys/smack.h>
35
36 #include "sysdeps.h"
37 #include "log.h"
38 #include "sdb.h"
39 #include "strutils.h"
40 #include "commandline_sdbd.h"
41 #include "utils.h"
42 #include "sdktools.h"
43 #include "plugin.h"
44 #include "sdbd_plugin.h"
45
46 #ifdef SUPPORT_ENCRYPT
47 #include "plugin_encrypt.h"
48 #endif
49
50 #include <linux/prctl.h>
51 #define SDB_PIDPATH "/tmp/.sdbd.pid"
52 #include <system_info.h>
53 #include <vconf.h>
54 #include <glib.h>
55
56 #define PROC_CMDLINE_PATH "/proc/cmdline"
57 #define USB_SERIAL_PATH "/sys/class/usb_mode/usb0/iSerial"
58 #define APPID2PID_PATH  "/usr/bin/appid2pid"
59
60 #include <sys/ioctl.h>
61 #include <net/if.h>
62 #include <netinet/in.h>
63 #include <arpa/inet.h>
64 #define GUEST_IP_INTERFACE "eth0"
65
66 SDB_MUTEX_DEFINE(zone_check_lock);
67 #if SDB_TRACE
68 SDB_MUTEX_DEFINE( D_lock );
69 #endif
70
71 #define SDB_LOGCONF_PATH "/tmp/.sdbdlog.conf"
72
73 int HOST = 0;
74
75 // sdk user
76 uid_t g_sdk_user_id;
77 gid_t g_sdk_group_id;
78 char* g_sdk_home_dir = NULL;
79 char* g_sdk_home_dir_env = NULL;
80 pcap g_capabilities;
81 int rootshell_mode; // 0: sdk user, 1: root
82 int booting_done; // 0: platform booting is in progess 1: platform booting is done
83
84 // root user
85 uid_t g_root_user_id;
86 gid_t g_root_group_id;
87 char* g_root_home_dir = NULL;
88 char* g_root_home_dir_env = NULL;
89
90 struct group_info
91 {
92     const char *name;
93     gid_t gid;
94 };
95 struct group_info g_default_groups[] = {
96     {"priv_externalstorage", -1},
97     {"priv_externalstorage_appdata", -1},
98     {"priv_mediastorage", -1},
99     {"log", -1},
100     {NULL, -1}
101 };
102
103 #define SDB_DEFAULT_GROUPS_CNT  ((sizeof(g_default_groups)/sizeof(g_default_groups[0]))-1)
104
105 int is_init_sdk_userinfo = 0;
106 int is_pwlocked = 0;    // 0 if unlocked, 1 otherwise
107
108 SdbdCommandlineArgs sdbd_commandline_args;
109
110 static int is_support_usbproto();
111 static int is_support_sockproto();
112
113 void (*usb_init)() = NULL;
114 void (*usb_cleanup)() = NULL;
115 int (*usb_write)(usb_handle *h, const void *data, int len) = NULL;
116 int (*usb_read)(usb_handle *h, void *data, size_t  len) = NULL;
117 int (*usb_close)(usb_handle *h) = NULL;
118 void (*usb_kick)(usb_handle *h) = NULL;
119
120 int g_is_emulator = -1;
121 int is_emulator(void) {
122     if (g_is_emulator >= 0) {
123         return g_is_emulator;
124     } else {
125         D("failed to initialize check emulator\n");
126     }
127
128     return sdbd_commandline_args.emulator.host != NULL;
129 }
130
131 int is_appid2pid_supported(void) {
132
133     if (access(APPID2PID_PATH, F_OK) == 0) {
134         /* It is necessary to confirm that it is possible
135          * to run "appid2pid" in the sdk user/group privileges. */
136         struct stat st;
137         if (stat(APPID2PID_PATH, &st) == 0) {
138             D("appid2pid uid=%d, gid=%d, mode=0x%x.\n", st.st_uid, st.st_gid, st.st_mode);
139             if ( (st.st_uid == STATIC_SDK_USER_ID && st.st_mode & S_IXUSR)
140                 || (st.st_gid == STATIC_SDK_GROUP_ID && st.st_mode & S_IXGRP)
141                 || (st.st_mode & S_IXOTH) ) {
142                 D("appid2pid is supported.\n");
143                 return 1;
144             }
145         }
146     } else {
147         D("failed to access appid2pid file: %d\n", errno);
148     }
149
150     D("appid2pid is NOT supported.\n");
151     return 0;
152 }
153
154 int is_container_enabled(void) {
155     bool value;
156     int ret;
157     ret = system_info_get_platform_bool("tizen.org/feature/container", &value);
158     if (ret != SYSTEM_INFO_ERROR_NONE) {
159         D("failed to get container information: %d\n", errno);
160         return 0;
161     } else {
162         D("tizen container: %d\n", value);
163         if (value == true)
164             return 1;
165         else
166             return 0;
167     }
168 }
169
170 void handle_sig_term(int sig) {
171 #ifdef SDB_PIDPATH
172     if (access(SDB_PIDPATH, F_OK) == 0)
173         sdb_unlink(SDB_PIDPATH);
174 #endif
175 }
176
177 static const char *sdb_device_banner = "device";
178
179 void fatal(const char *fmt, ...)
180 {
181     va_list ap;
182     va_start(ap, fmt);
183     fprintf(stderr, "error: ");
184     vfprintf(stderr, fmt, ap);
185     fprintf(stderr, "\n");
186     va_end(ap);
187     exit(-1);
188 }
189
190 void fatal_errno(const char *fmt, ...)
191 {
192     va_list ap;
193     va_start(ap, fmt);
194     fprintf(stderr, "errno: %d: ", errno);
195     vfprintf(stderr, fmt, ap);
196     fprintf(stderr, "\n");
197     va_end(ap);
198     exit(-1);
199 }
200
201 static char* get_sdb_log_conf(const char* key)
202 {
203     int fd;
204     char line[256] = {0,};
205     char value[256] = {0,};
206
207     if (access(SDB_LOGCONF_PATH, F_OK)) {
208         return NULL;
209     }
210
211     fd = unix_open(SDB_LOGCONF_PATH, O_RDONLY);
212     if (fd < 0) {
213         D("failed to open '%s' file: %d\n", SDB_LOGCONF_PATH, errno);
214         return NULL;
215     }
216
217     if (read_line(fd, line, sizeof(line)) > 0) {
218         char* start = strstr(line, key);
219         if (start != NULL) {
220             // move one more character to remove '=',
221             // including the length of the key string
222             start = start + strlen(key) + 1;
223             char* end = strstr(start, " ");
224             if (end != NULL) {
225                 strncpy(value, start, end - start);
226             } else {
227                 strncpy(value, start, sizeof(value));
228             }
229         } else {
230             sdb_close(fd);
231             return NULL;
232         }
233     }
234     sdb_close(fd);
235     return strdup(value);
236 }
237
238 static int is_enable_sdbd_log()
239 {
240     return (!strncmp(g_capabilities.log_enable, PLUGIN_RET_ENABLED, strlen(PLUGIN_RET_ENABLED)));
241 }
242
243 int   sdb_trace_mask;
244
245 /* read a comma/space/colum/semi-column separated list of tags
246  * from the SDB_TRACE environment variable and build the trace
247  * mask from it. note that '1' and 'all' are special cases to
248  * enable all tracing
249  */
250 void  sdb_trace_init(void)
251 {
252     char*  ptr = get_sdb_log_conf("SDB_TRACE");
253     const char*  p;
254     const char*  q;
255
256     static const struct {
257         const char*  tag;
258         int           flag;
259     } tags[] = {
260         { "1", 0 },
261         { "all", 0 },
262         { "sdb", TRACE_SDB },
263         { "sockets", TRACE_SOCKETS },
264         { "packets", TRACE_PACKETS },
265         { "rwx", TRACE_RWX },
266         { "usb", TRACE_USB },
267         { "sync", TRACE_SYNC },
268         { "sysdeps", TRACE_SYSDEPS },
269         { "transport", TRACE_TRANSPORT },
270         { "jdwp", TRACE_JDWP },
271         { "services", TRACE_SERVICES },
272         { "properties", TRACE_PROPERTIES },
273         { "sdktools", TRACE_SDKTOOLS },
274         { "appcmd", TRACE_APPCMD },
275         { NULL, 0 }
276     };
277
278     if (ptr == NULL) {
279         if (is_enable_sdbd_log())
280             p = "all";
281         else
282             return;
283     } else {
284         p = ptr;
285     }
286
287     /* use a comma/column/semi-colum/space separated list */
288     while (*p) {
289         int  len, tagn;
290
291         q = strpbrk(p, " ,:;");
292         if (q == NULL) {
293             q = p + strlen(p);
294         }
295         len = q - p;
296
297         for (tagn = 0; tags[tagn].tag != NULL; tagn++)
298         {
299             int  taglen = strlen(tags[tagn].tag);
300
301             if (len == taglen && !memcmp(tags[tagn].tag, p, len) )
302             {
303                 int  flag = tags[tagn].flag;
304                 if (flag == 0) {
305                     sdb_trace_mask = ~0;
306                     free(ptr);
307                     return;
308                 }
309                 sdb_trace_mask |= (1 << flag);
310                 break;
311             }
312         }
313         p = q;
314         if (*p)
315             p++;
316     }
317     free(ptr);
318 }
319
320 /*
321  * Implements SDB tracing inside the emulator.
322  */
323
324 #include <stdarg.h>
325
326 /*
327  * Redefine open and write for qemu_pipe.h that contains inlined references
328  * to those routines. We will redifine them back after qemu_pipe.h inclusion.
329  */
330
331 #undef open
332 #undef write
333 #define open    sdb_open
334 #define write   sdb_write
335 #include "qemu_pipe.h"
336 #undef open
337 #undef write
338 #define open    ___xxx_open
339 #define write   ___xxx_write
340
341 /* A handle to sdb-debug qemud service in the emulator. */
342 int   sdb_debug_qemu = -1;
343
344 apacket *get_apacket(void)
345 {
346     apacket *p = malloc(sizeof(apacket));
347     if(p == 0) fatal("failed to allocate an apacket");
348     memset(p, 0, sizeof(apacket) - MAX_PAYLOAD);
349     return p;
350 }
351
352 void put_apacket(apacket *p)
353 {
354     if (p != NULL) {
355         free(p);
356         p = NULL;
357     }
358 }
359
360 void handle_online(void)
361 {
362     D("sdb: online\n");
363 }
364
365 void handle_offline(atransport *t)
366 {
367     D("sdb: offline\n");
368     //Close the associated usb
369     run_transport_disconnects(t);
370 }
371
372 #if TRACE_PACKETS
373 #define DUMPMAX 32
374 void print_packet(const char *label, apacket *p)
375 {
376     char *tag;
377     char *x;
378     unsigned count;
379
380     switch(p->msg.command){
381     case A_SYNC: tag = "SYNC"; break;
382     case A_CNXN: tag = "CNXN" ; break;
383     case A_OPEN: tag = "OPEN"; break;
384     case A_OKAY: tag = "OKAY"; break;
385     case A_CLSE: tag = "CLSE"; break;
386     case A_WRTE: tag = "WRTE"; break;
387     default: tag = "????"; break;
388     }
389
390     fprintf(stderr, "%s: %s %08x %08x %04x \"",
391             label, tag, p->msg.arg0, p->msg.arg1, p->msg.data_length);
392     count = p->msg.data_length;
393     x = (char*) p->data;
394     if(count > DUMPMAX) {
395         count = DUMPMAX;
396         tag = "\n";
397     } else {
398         tag = "\"\n";
399     }
400     while(count-- > 0){
401         if((*x >= ' ') && (*x < 127)) {
402             fputc(*x, stderr);
403         } else {
404             fputc('.', stderr);
405         }
406         x++;
407     }
408     fprintf(stderr, tag);
409 }
410 #endif
411
412 #ifdef SUPPORT_ENCRYPT
413 /*
414 desc. : 암호화 실패 메시지 전송
415 parameter : [in] apacket* p : sdbd로 들어온 메시지
416             [in] atransport *t : 현재 연결에 대한 atransport
417             [in] unsigned failed_value : 실패 값
418 */
419 void send_encr_fail(apacket* p, atransport *t, unsigned failed_value){
420     apacket* enc_p;
421     enc_p = get_apacket();
422     enc_p->msg.command = A_ENCR; // 암호화 메시지
423     enc_p->msg.arg0 = failed_value; // 실패값
424     enc_p->msg.arg1 = p->msg.arg1;
425     send_packet(enc_p, t);
426     //put_apacket(enc_p);
427 }
428
429 /*
430 desc. : 암호화 메시지 핸들링
431 parameter : [in] apacket* p : sdbd로 들어온 메시지
432             [in/out] atransport *t : 현재 연결에 대한 atransport
433 ret : 0 : 정상적으로 메시지 전송
434       -1: 메시지 전송 실패
435 */
436 int handle_encr_packet(apacket* p, atransport *t){
437     static int sessionID = 0;
438     int retVal = 0;
439     apacket* enc_p = NULL;
440
441     if(p->msg.arg0 == ENCR_SET_ON_REQ){ // hello 메시지인 경우
442         t->sessionID = sessionID;
443         if((retVal = security_init(t->sessionID, NULL)) == 1){ // 암호화 handshaking을 위한 init
444             if(security_parse_server_hello(t->sessionID, p) == 1){ // hello 메시지 파싱
445                 D("security_parse_server_hello success\n");
446                 enc_p = get_apacket();
447                 if(security_gen_client_hello(t->sessionID, enc_p) == 1){ // hello 메시지 생성
448                     D("security_gen_client_hello success\n");
449                     enc_p->msg.command = A_ENCR;
450                     enc_p->msg.arg0 = ENCR_SET_ON_REQ;
451                     enc_p->msg.arg1 = p->msg.arg1;
452                     sessionID++;
453                     send_packet(enc_p, t);
454                 }
455                 else { // hello 메시지 생성 실패
456                     D("security_gen_client_hello error\n");
457                     send_encr_fail(p, t, ENCR_ON_FAIL); // 암호화 on 실패 메시지 전송
458                     t->encryption = ENCR_OFF; // 암호화 모드는 off
459                     security_deinit(t->sessionID);
460                     return -1;
461                 }
462             }
463             else{ // hello 메시지 파싱 실패
464                 D("security_parse_server_hello error\n");
465                 send_encr_fail(p, t, ENCR_ON_FAIL);
466                 t->encryption = ENCR_OFF;
467                 security_deinit(t->sessionID);
468
469                 return -1;
470             }
471         } else { // init 실패
472             D("security_init error\n");
473             send_encr_fail(p, t, ENCR_ON_FAIL);
474             t->encryption = ENCR_OFF;
475             if (retVal == 0)
476             {
477                 security_deinit(t->sessionID);
478             }
479             //here!! do security_deinit(), but when plugin pointer is null -> not deinit
480             return -1;
481         }
482     }
483     else if(p->msg.arg0 == ENCR_SET_ON_OK){ // ack 메시지인 경우
484         if(security_parse_server_ack(t->sessionID, p) == 1){    // ack 메시지 파싱
485             enc_p = get_apacket();
486             if(security_gen_client_ack(t->sessionID, enc_p) == 1){ // ack 메시지 생성
487                 D("security_gen_client_ack success\n");
488                 enc_p->msg.command = A_ENCR;
489                 enc_p->msg.arg0 = ENCR_SET_ON_OK;
490                 enc_p->msg.arg1 = p->msg.arg1;
491                 t->encryption = ENCR_ON;
492                 send_packet(enc_p, t);
493             }
494             else { // ack 메시지 생성에 실패한 경우
495                 D("security_gen_client_ack error\n");
496                 send_encr_fail(p, t, ENCR_ON_FAIL);
497                 t->encryption = ENCR_OFF;
498                 security_deinit(t->sessionID);
499                 return -1;
500             }
501         }
502         else { // ack 메시지 파싱에 실패한 경우
503             D("security_parse_server_ack error\n");
504             send_encr_fail(p, t, ENCR_ON_FAIL);
505             t->encryption = ENCR_OFF;
506             security_deinit(t->sessionID);
507             return -1;
508         }
509     }
510     else if(p->msg.arg0 == ENCR_SET_OFF){ // 암호화 모드 off 요청 메시지
511         if(t->encryption == ENCR_ON && security_deinit(t->sessionID) == 1){ // 현재 암호화 모드가 on 상태인 경우
512             enc_p = get_apacket();
513             t->encryption = ENCR_OFF; // 현재 연결에 대한 암호화 모드 off
514             enc_p->msg.command = A_ENCR;
515             enc_p->msg.arg0 = ENCR_SET_OFF;
516             enc_p->msg.arg1 = p->msg.arg1;
517             send_packet(enc_p, t);
518         }
519         else { // 암호화 모드 off에 실패한 경우
520             D("security_deinit error\n");
521             send_encr_fail(p, t, ENCR_OFF_FAIL); // 암호화 모드 off 실패 메시지 전송
522             return -1;
523         }
524     }
525     else if(p->msg.arg0 == ENCR_GET){ // 암호화 모드의 상태 요청 메시지인 경우
526         enc_p = get_apacket();
527         enc_p->msg.command = A_ENCR;
528         enc_p->msg.arg0 = ENCR_GET; // 암호화 모드 status get메시지
529         enc_p->msg.arg1 = p->msg.arg1;
530         if(t->encryption == ENCR_ON){ // 암호화 모드가 on인 경우
531             enc_p->msg.data_length = 13;
532             strncpy((char*)enc_p->data, "encryption:on", enc_p->msg.data_length); // encryption:on 메시지 전송
533         } else if(t->encryption == ENCR_OFF){ // 암호화 모드가 off인 경우
534             enc_p->msg.data_length = 14;
535             strncpy((char*)enc_p->data, "encryption:off", enc_p->msg.data_length); // encryption:off 메시지 전송
536         }
537         send_packet(enc_p, t);
538     }
539     else if (p->msg.arg0 == ENCR_ON_FAIL) // 암호화 모드를 on 하는 도중 실패한 경우 받는 메시지
540     {
541         t->encryption = ENCR_OFF; // 암호화 모드를 다시 off
542         D("encryption on failed\n");
543     }
544     else if (p->msg.arg0 == ENCR_OFF_FAIL) // 암호화 모드를 off하는 도중 실패한 경우 받는 메시지
545     {
546         //t->encryption = ENCR_ON;
547         D("encryption off failed\n");
548     }
549     //put_apacket(enc_p);
550     return 0;
551
552 }
553 #endif
554
555
556 static void send_ready(unsigned local, unsigned remote, atransport *t)
557 {
558     D("Calling send_ready \n");
559     apacket *p = get_apacket();
560     p->msg.command = A_OKAY;
561     p->msg.arg0 = local;
562     p->msg.arg1 = remote;
563     send_packet(p, t);
564 }
565
566 static void send_close(unsigned local, unsigned remote, atransport *t)
567 {
568     D("Calling send_close \n");
569     apacket *p = get_apacket();
570     p->msg.command = A_CLSE;
571     p->msg.arg0 = local;
572     p->msg.arg1 = remote;
573     send_packet(p, t);
574 }
575
576 static void send_connect(atransport *t)
577 {
578     D("Calling send_connect \n");
579     apacket *cp = get_apacket();
580     cp->msg.command = A_CNXN;
581     cp->msg.arg0 = A_VERSION;
582 #ifdef SUPPORT_ENCRYPT
583    cp->msg.arg1 = MAX_PAYLOAD - 100; // connection 시, sdb server의 패킷 크기를 암호화 오버로드 만큼 줄임
584 #else
585     cp->msg.arg1 = MAX_PAYLOAD;
586 #endif
587     char device_name[256]={0,};
588     int r = 0;
589     int status = 0;
590     if (request_lock_state_to_plugin(LOCKTYPE_PASSWORD) == 1) {
591         status = 1;
592         t->connection_state = CS_PWLOCK;
593     }
594
595     if (is_emulator()) {
596         r = get_emulator_name(device_name, sizeof device_name);
597     } else {
598         r = get_device_name(device_name, sizeof device_name);
599     }
600     if (r < 0) {
601         snprintf((char*) cp->data, sizeof cp->data, "%s::%s::%d", sdb_device_banner, DEFAULT_DEVICENAME, status);
602     } else {
603         snprintf((char*) cp->data, sizeof cp->data, "%s::%s::%d", sdb_device_banner, device_name, status);
604     }
605
606     D("CNXN data:%s\n", (char*)cp->data);
607     cp->msg.data_length = strlen((char*) cp->data) + 1;
608
609     send_packet(cp, t);
610 }
611
612 void send_device_status()
613 {
614     D("broadcast device status\n");
615     apacket* cp = get_apacket();
616     cp->msg.command = A_STAT;
617     cp->msg.arg0 = is_pwlocked;
618     cp->msg.arg1 = 0;
619
620     broadcast_transport(cp);
621
622     //all broadcasted packets are memory copied
623     //so, we should call put_apacket
624     put_apacket(cp);
625 }
626
627 static char *connection_state_name(atransport *t)
628 {
629     if (t == NULL) {
630         return "unknown";
631     }
632
633     switch(t->connection_state) {
634     case CS_BOOTLOADER:
635         return "bootloader";
636     case CS_DEVICE:
637         return "device";
638     case CS_OFFLINE:
639         return "offline";
640     default:
641         return "unknown";
642     }
643 }
644
645 static int get_str_cmdline(char *src, char *dest, char str[], int str_size) {
646     char *s = strstr(src, dest);
647     if (s == NULL) {
648         return -1;
649     }
650     char *e = strstr(s, " ");
651     if (e == NULL) {
652         return -1;
653     }
654
655     int len = e-s-strlen(dest);
656
657     if (len >= str_size) {
658         D("buffer size(%d) should be bigger than %d\n", str_size, len+1);
659         return -1;
660     }
661
662     strncpy(str, s + strlen(dest), len);
663     str[len]='\0';
664     return len;
665 }
666
667 int get_emulator_forward_port() {
668     SdbdCommandlineArgs *sdbd_args = &sdbd_commandline_args; /* alias */
669
670     if (sdbd_args->emulator.host == NULL) {
671         return -1;
672     }
673
674     return sdbd_args->emulator.port;
675 }
676
677 int get_emulator_name(char str[], int str_size) {
678     SdbdCommandlineArgs *sdbd_args = &sdbd_commandline_args; /* alias */
679
680     if (sdbd_args->emulator.host == NULL) {
681         return -1;
682     }
683
684     s_strncpy(str, sdbd_args->emulator.host, str_size);
685     return 0;
686 }
687
688 int get_device_name(char str[], int str_size) {
689     char *value = NULL;
690     int r = system_info_get_platform_string("http://tizen.org/system/model_name", &value);
691     if (r != SYSTEM_INFO_ERROR_NONE) {
692         D("fail to get system model:%d\n", errno);
693         return -1;
694     } else {
695         s_strncpy(str, value, str_size);
696         D("returns model_name:%s\n", value);
697         if (value != NULL) {
698             free(value);
699         }
700         return 0;
701     }
702     /*
703     int fd = unix_open(USB_SERIAL_PATH, O_RDONLY);
704     if (fd < 0) {
705         D("fail to read:%s (%d)\n", USB_SERIAL_PATH, errno);
706         return -1;
707     }
708
709     if(read_line(fd, str, str_size)) {
710         D("device serial name: %s\n", str);
711         sdb_close(fd);
712         return 0;
713     }
714     sdb_close(fd);
715     */
716     return -1;
717 }
718
719 static int get_cmdline_value(char *split, char str[], int str_size) {
720     char cmdline[512];
721     int fd = unix_open(PROC_CMDLINE_PATH, O_RDONLY);
722
723     if (fd < 0) {
724         D("fail to read /proc/cmdline\n");
725         return -1;
726     }
727     if(read_line(fd, cmdline, sizeof(cmdline))) {
728         D("qemu cmd: %s\n", cmdline);
729         if (get_str_cmdline(cmdline, split, str, str_size) < 1) {
730             D("could not get the (%s) value from cmdline\n", split);
731             sdb_close(fd);
732             return -1;
733         }
734     }
735     sdb_close(fd);
736     return 0;
737 }
738
739 int get_emulator_hostip(char str[], int str_size) {
740     return get_cmdline_value("host_ip=", str, str_size);
741 }
742
743 int get_emulator_guestip(char str[], int str_size) {
744     int           s;
745     struct ifreq ifr;
746     struct sockaddr_in *sin;
747
748     s = socket(AF_INET, SOCK_DGRAM, 0);
749     if(s < 0) {
750         D("socket error\n");
751         return -1;
752     }
753
754     snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", GUEST_IP_INTERFACE);
755     if(ioctl(s, SIOCGIFHWADDR, &ifr) < 0) {
756         D("ioctl hwaddr error\n");
757         sdb_close(s);
758         return -1;
759     }
760
761     if(ioctl(s, SIOCGIFADDR, &ifr) < 0) {
762         D("ioctl addr error\n");
763         sdb_close(s);
764         return -1;
765     }
766     sin = (struct sockaddr_in *)&ifr.ifr_addr;
767     snprintf(str, str_size, "%s", inet_ntoa(sin->sin_addr));
768     sdb_close(s);
769
770     return 0;
771 }
772
773 void parse_banner(char *banner, atransport *t)
774 {
775     char *type, *product, *end;
776
777     D("parse_banner: %s\n", banner);
778     type = banner;
779     product = strchr(type, ':');
780     if(product) {
781         *product++ = 0;
782     } else {
783         product = "";
784     }
785
786         /* remove trailing ':' */
787     end = strchr(product, ':');
788     if(end) *end = 0;
789
790         /* save product name in device structure */
791     if (t->product == NULL) {
792         t->product = strdup(product);
793     } else if (strcmp(product, t->product) != 0) {
794         free(t->product);
795         t->product = strdup(product);
796     }
797
798     if(!strcmp(type, "bootloader")){
799         D("setting connection_state to CS_BOOTLOADER\n");
800         t->connection_state = CS_BOOTLOADER;
801         update_transports();
802         return;
803     }
804
805     if(!strcmp(type, "device")) {
806         D("setting connection_state to CS_DEVICE\n");
807         t->connection_state = CS_DEVICE;
808         update_transports();
809         return;
810     }
811
812     if(!strcmp(type, "recovery")) {
813         D("setting connection_state to CS_RECOVERY\n");
814         t->connection_state = CS_RECOVERY;
815         update_transports();
816         return;
817     }
818
819     if(!strcmp(type, "sideload")) {
820         D("setting connection_state to CS_SIDELOAD\n");
821         t->connection_state = CS_SIDELOAD;
822         update_transports();
823         return;
824     }
825
826     t->connection_state = CS_HOST;
827 }
828
829 static void update_version(atransport *t, int version, size_t payload)
830 {
831 #ifdef SUPPORT_ENCRYPT
832     size_t max_payload = MAX_PAYLOAD - 100;
833 #else
834     size_t max_payload = MAX_PAYLOAD;
835 #endif
836     t->protocol_version = min(version, A_VERSION);
837     t->max_payload = min(payload, max_payload);
838     D("update transport version. version=%x, max_payload=%zu\n", t->protocol_version, t->max_payload);
839 }
840
841 void handle_packet(apacket *p, atransport *t)
842 {
843     // Verify pointer p
844     int result = access((const char *) p, F_OK);
845     if ((result == -1) && (errno == EFAULT)) {
846         fatal("Invalid apacket = [0x%p]", p);
847     }
848
849     asocket *s;
850
851     D("handle_packet() %c%c%c%c\n", ((char*) (&(p->msg.command)))[0],
852                 ((char*) (&(p->msg.command)))[1],
853                 ((char*) (&(p->msg.command)))[2],
854                 ((char*) (&(p->msg.command)))[3]);
855
856     print_packet("recv", p);
857
858     switch(p->msg.command){
859     case A_SYNC:
860         if(p->msg.arg0){
861             send_packet(p, t);
862             if(HOST) send_connect(t);
863         } else {
864             t->connection_state = CS_OFFLINE;
865             handle_offline(t);
866             send_packet(p, t);
867         }
868         return;
869
870     case A_CNXN: /* CONNECT(version, maxdata, "system-id-string") */
871             /* XXX verify version, etc */
872         if(t->connection_state != CS_OFFLINE) {
873             t->connection_state = CS_OFFLINE;
874             handle_offline(t);
875         }
876         update_version(t, p->msg.arg0, p->msg.arg1);
877         parse_banner((char*) p->data, t);
878         handle_online();
879         if(!HOST) send_connect(t);
880         break;
881
882     case A_OPEN: /* OPEN(local-id, 0, "destination") */
883         if (request_lock_state_to_plugin(LOCKTYPE_PASSWORD) == 1 && t->connection_state == CS_PWLOCK) {
884             // in case of already locked before get A_CNXN
885             D("open failed due to password locked before get A_CNXN:%d\n", t->connection_state);
886             send_close(0, p->msg.arg0, t);
887         } else {
888             if(t->connection_state != CS_OFFLINE) {
889                 char *name = (char*) p->data;
890                 name[p->msg.data_length > 0 ? p->msg.data_length - 1 : 0] = 0;
891                 s = create_local_service_socket(name);
892                 if(s == 0) {
893                     send_close(0, p->msg.arg0, t);
894                 } else {
895                     s->peer = create_remote_socket(p->msg.arg0, t);
896                     s->peer->peer = s;
897                     send_ready(s->id, s->peer->id, t);
898                     s->ready(s);
899                 }
900             }
901         }
902         break;
903
904     case A_OKAY: /* READY(local-id, remote-id, "") */
905         if(t->connection_state != CS_OFFLINE) {
906             if((s = find_local_socket(p->msg.arg1))) {
907                 if(s->peer == 0) {
908                     s->peer = create_remote_socket(p->msg.arg0, t);
909                     s->peer->peer = s;
910                 }
911                 s->ready(s);
912             }
913         }
914         break;
915
916     case A_CLSE: /* CLOSE(local-id, remote-id, "") */
917         if(t->connection_state != CS_OFFLINE) {
918             if((s = find_local_socket(p->msg.arg1))) {
919                 s->close(s);
920             }
921         }
922         break;
923
924     case A_WRTE:
925         if(t->connection_state != CS_OFFLINE) {
926             if((s = find_local_socket(p->msg.arg1))) {
927                 unsigned rid = p->msg.arg0;
928                 p->len = p->msg.data_length;
929
930                 if(s->enqueue(s, p) == 0) {
931                     D("Enqueue the socket\n");
932                     send_ready(s->id, rid, t);
933                 }
934                 return;
935             }
936         }
937         break;
938 #ifdef SUPPORT_ENCRYPT
939     case A_ENCR: // 암호화 메시지인 경우
940         if(t->connection_state != CS_OFFLINE) {
941             handle_encr_packet(p, t);
942         }
943         break;
944 #endif
945
946     default:
947         printf("handle_packet: what is %08x?!\n", p->msg.command);
948     }
949
950     put_apacket(p);
951 }
952
953 alistener listener_list = {
954     .next = &listener_list,
955     .prev = &listener_list,
956 };
957
958 static void ss_listener_event_func(int _fd, unsigned ev, void *_l)
959 {
960     asocket *s;
961
962     if(ev & FDE_READ) {
963         struct sockaddr addr;
964         socklen_t alen;
965         int fd;
966
967         alen = sizeof(addr);
968         fd = sdb_socket_accept(_fd, &addr, &alen);
969         if(fd < 0) return;
970
971         sdb_socket_setbufsize(fd, CHUNK_SIZE);
972
973         s = create_local_socket(fd);
974         if(s) {
975             connect_to_smartsocket(s);
976             return;
977         }
978
979         sdb_close(fd);
980     }
981 }
982
983 static void listener_event_func(int _fd, unsigned ev, void *_l)
984 {
985     alistener *l = _l;
986     asocket *s;
987
988     if(ev & FDE_READ) {
989         struct sockaddr addr;
990         socklen_t alen;
991         int fd;
992
993         alen = sizeof(addr);
994         fd = sdb_socket_accept(_fd, &addr, &alen);
995         if(fd < 0) return;
996
997         s = create_local_socket(fd);
998         if(s) {
999             s->transport = l->transport;
1000             connect_to_remote(s, l->connect_to);
1001             return;
1002         }
1003
1004         sdb_close(fd);
1005     }
1006 }
1007
1008 static void  free_listener(alistener*  l)
1009 {
1010     if (l->next) {
1011         l->next->prev = l->prev;
1012         l->prev->next = l->next;
1013         l->next = l->prev = l;
1014     }
1015
1016     // closes the corresponding fd
1017     fdevent_remove(&l->fde);
1018
1019     if (l->local_name)
1020         free((char*)l->local_name);
1021
1022     if (l->connect_to)
1023         free((char*)l->connect_to);
1024
1025     if (l->transport) {
1026         remove_transport_disconnect(l->transport, &l->disconnect);
1027     }
1028     free(l);
1029 }
1030
1031 static void listener_disconnect(void*  _l, atransport*  t)
1032 {
1033     alistener*  l = _l;
1034
1035     free_listener(l);
1036 }
1037
1038 int local_name_to_fd(const char *name)
1039 {
1040     int port;
1041
1042     if(!strncmp("tcp:", name, 4)){
1043         int  ret;
1044         port = atoi(name + 4);
1045         ret = socket_loopback_server(port, SOCK_STREAM);
1046         return ret;
1047     }
1048 #ifndef HAVE_WIN32_IPC  /* no Unix-domain sockets on Win32 */
1049     // It's non-sensical to support the "reserved" space on the sdb host side
1050     if(!strncmp(name, "local:", 6)) {
1051         return socket_local_server(name + 6,
1052                 ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
1053     } else if(!strncmp(name, "localabstract:", 14)) {
1054         return socket_local_server(name + 14,
1055                 ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
1056     } else if(!strncmp(name, "localfilesystem:", 16)) {
1057         return socket_local_server(name + 16,
1058                 ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
1059     }
1060
1061 #endif
1062     printf("unknown local portname '%s'\n", name);
1063     return -1;
1064 }
1065
1066 static int remove_listener(const char *local_name, const char *connect_to, atransport* transport)
1067 {
1068     alistener *l;
1069
1070     for (l = listener_list.next; l != &listener_list; l = l->next) {
1071         if (!strcmp(local_name, l->local_name) &&
1072             !strcmp(connect_to, l->connect_to) &&
1073             l->transport && l->transport == transport) {
1074
1075             listener_disconnect(l, transport);
1076             return 0;
1077         }
1078     }
1079
1080     return -1;
1081 }
1082
1083 static int install_listener(const char *local_name, const char *connect_to, atransport* transport)
1084 {
1085     alistener *l;
1086
1087     //printf("install_listener('%s','%s')\n", local_name, connect_to);
1088
1089     for(l = listener_list.next; l != &listener_list; l = l->next){
1090         if(strcmp(local_name, l->local_name) == 0) {
1091             char *cto;
1092
1093                 /* can't repurpose a smartsocket */
1094             if(l->connect_to[0] == '*') {
1095                 return -1;
1096             }
1097
1098             cto = strdup(connect_to);
1099             if(cto == 0) {
1100                 return -1;
1101             }
1102
1103             //printf("rebinding '%s' to '%s'\n", local_name, connect_to);
1104             free((void*) l->connect_to);
1105             l->connect_to = cto;
1106             if (l->transport != transport) {
1107                 remove_transport_disconnect(l->transport, &l->disconnect);
1108                 l->transport = transport;
1109                 add_transport_disconnect(l->transport, &l->disconnect);
1110             }
1111             return 0;
1112         }
1113     }
1114
1115     if((l = calloc(1, sizeof(alistener))) == 0) goto nomem;
1116     if((l->local_name = strdup(local_name)) == 0) goto nomem;
1117     if((l->connect_to = strdup(connect_to)) == 0) goto nomem;
1118
1119
1120     l->fd = local_name_to_fd(local_name);
1121     if(l->fd < 0) {
1122         free((void*) l->local_name);
1123         free((void*) l->connect_to);
1124         free(l);
1125         printf("cannot bind '%s'\n", local_name);
1126         return -2;
1127     }
1128
1129     if (close_on_exec(l->fd) < 0) {
1130         D("fail to close fd exec:%d\n",l->fd);
1131     }
1132     if(!strcmp(l->connect_to, "*smartsocket*")) {
1133         fdevent_install(&l->fde, l->fd, ss_listener_event_func, l);
1134     } else {
1135         fdevent_install(&l->fde, l->fd, listener_event_func, l);
1136     }
1137     fdevent_set(&l->fde, FDE_READ);
1138
1139     l->next = &listener_list;
1140     l->prev = listener_list.prev;
1141     l->next->prev = l;
1142     l->prev->next = l;
1143     l->transport = transport;
1144
1145     if (transport) {
1146         l->disconnect.opaque = l;
1147         l->disconnect.func   = listener_disconnect;
1148         add_transport_disconnect(transport, &l->disconnect);
1149     }
1150     return 0;
1151
1152 nomem:
1153     fatal("cannot allocate listener");
1154     return 0;
1155 }
1156
1157 static void sdb_cleanup(void)
1158 {
1159     clear_sdbd_commandline_args(&sdbd_commandline_args);
1160
1161     if (is_support_usbproto()) {
1162         usb_cleanup();
1163     }
1164 //    if(required_pid > 0) {
1165 //        kill(required_pid, SIGKILL);
1166 //    }
1167
1168     unload_sdbd_plugin();
1169 }
1170
1171 void start_device_log(void)
1172 {
1173     int fd;
1174     char    path[PATH_MAX] = {0, };
1175     char    path_folder[PATH_MAX] = {0, };
1176     char    path_file[PATH_MAX] = {0, };
1177     struct tm now;
1178     time_t t;
1179
1180     // read the trace mask from persistent property persist.sdb.trace_mask
1181     // give up if the property is not set or cannot be parsed
1182     char* p_trace = get_sdb_log_conf("SDB_TRACE");
1183     if ((p_trace == NULL ) && !is_enable_sdbd_log()) {
1184         return;
1185     } else {
1186         free(p_trace);
1187     }
1188     char* p_path = get_sdb_log_conf("SDBD_LOG_PATH");
1189     if (p_path) {
1190         snprintf(path_folder, sizeof(path_folder), "%s", p_path);
1191         free(p_path);
1192     } else if (g_capabilities.log_path[0] != '\0') {
1193         snprintf(path_folder, sizeof(path_folder), "%s", g_capabilities.log_path);
1194     } else {
1195         return;
1196     }
1197
1198     tzset();
1199     time(&t);
1200     localtime_r(&t, &now);
1201
1202     strftime(path_file, sizeof(path_file),
1203                     "sdbd-%Y-%m-%d-%H-%M-%S.txt",
1204                     &now);
1205
1206     snprintf(path, sizeof(path), "%s/%s", path_folder, path_file);
1207
1208     fd = unix_open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
1209     if (fd < 0) {
1210         return;
1211     }
1212
1213     // redirect stdout and stderr to the log file
1214     dup2(fd, 1);
1215     dup2(fd, 2);
1216     fprintf(stderr,"--- sdbd starting (pid %d) ---\n", getpid());
1217     sdb_close(fd);
1218
1219     fd = unix_open("/dev/null", O_RDONLY);
1220     if (fd < 0) {
1221         // hopefully not gonna happen
1222         return;
1223     }
1224     dup2(fd, 0);
1225     sdb_close(fd);
1226 }
1227
1228 int daemonize(void) {
1229
1230     // set file creation mask to 0
1231     umask(0);
1232
1233     switch (fork()) {
1234     case -1:
1235         return -1;
1236     case 0:
1237         break;
1238     default:
1239         _exit(0);
1240     }
1241 #ifdef SDB_PIDPATH
1242     char* tmppath = NULL;
1243     tmppath = realpath(SDB_PIDPATH, NULL);
1244     if (tmppath == NULL && errno == ENOENT) {
1245         FILE *f = fopen(SDB_PIDPATH, "w");
1246
1247         if (f != NULL) {
1248             fprintf(f, "%d\n", getpid());
1249             fclose(f);
1250         }
1251     } else {
1252         D("sdbd: %s file is existed. It might not work properly.\n", SDB_PIDPATH);
1253         free(tmppath);
1254     }
1255 #endif
1256     if (setsid() == -1)
1257         return -1;
1258
1259     if (chdir("/") < 0)
1260         D("sdbd: unable to change working directory to /\n");
1261
1262     return 0;
1263 }
1264
1265 /* Constructs a local name of form tcp:port.
1266  * target_str points to the target string, it's content will be overwritten.
1267  * target_size is the capacity of the target string.
1268  * server_port is the port number to use for the local name.
1269  */
1270 void build_local_name(char* target_str, size_t target_size, int server_port)
1271 {
1272   snprintf(target_str, target_size, "tcp:%d", server_port);
1273 }
1274
1275 static void init_drop_privileges() {
1276 #ifdef _DROP_PRIVILEGE
1277     rootshell_mode = 0;
1278 #else
1279     rootshell_mode = 1;
1280 #endif
1281 }
1282
1283 int should_drop_privileges() {
1284     if (rootshell_mode == 1) { // if root, then don't drop
1285         return 0;
1286     }
1287     return 1;
1288 }
1289
1290 #include <gio/gio.h>
1291
1292 #define DEVICED_BUS            "org.tizen.system.deviced"
1293 #define DEVICED_CORE_PATH      "/Org/Tizen/System/DeviceD/Core"
1294 #define BOOTING_DONE_SIGNAL    "BootingDone"
1295 #define DEVICED_CORE_INTERFACE "org.tizen.system.deviced.core"
1296 #define SDBD_BOOT_INFO_FILE    "/tmp/sdbd_boot_info"
1297
1298 static GMainLoop *g_mainloop;
1299
1300 static void booting_done_signal_subscriber(GDBusConnection *connection,
1301     const gchar *sender, const gchar *path, const gchar *interface,
1302     const gchar *signal, GVariant *parameters, gpointer user_data)
1303 {
1304     if (g_strcmp0(signal, BOOTING_DONE_SIGNAL) != 0) {
1305         D("received signal(%s) does not match the desired signal(%s)\n",
1306           signal, BOOTING_DONE_SIGNAL);
1307         return;
1308     }
1309
1310     D("received the \"%s\" signal\n", signal);
1311
1312     booting_done = 1;
1313     if (access(SDBD_BOOT_INFO_FILE, F_OK) == 0) {
1314         D("booting is already done\n");
1315     } else {
1316         FILE *info_file = fopen(SDBD_BOOT_INFO_FILE, "w");
1317         if (info_file != NULL) {
1318             fprintf(info_file, "%d", 1);
1319             fclose(info_file);
1320         }
1321         D("booting is done\n");
1322     }
1323
1324     D("handled the booting done signal\n");
1325     g_main_loop_quit(g_mainloop);
1326 }
1327
1328 static void *bootdone_cb(void *args)
1329 {
1330     GError *error = NULL;
1331     GDBusConnection *connection = NULL;
1332     guint id;
1333
1334     connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
1335     if (connection == NULL) {
1336         if (error != NULL) {
1337             D("failed to connect to the system bus: %s\n", error->message);
1338             g_error_free(error);
1339         } else {
1340             D("failed to connect to the system bus\n");
1341         }
1342         return NULL;
1343     }
1344
1345     g_mainloop = g_main_loop_new(NULL, false);
1346     if (g_mainloop == NULL) {
1347         D("failed to create a g_main_loop\n");
1348         goto bootdone_out;
1349     }
1350
1351     id = g_dbus_connection_signal_subscribe(connection,
1352         DEVICED_BUS, DEVICED_CORE_INTERFACE, BOOTING_DONE_SIGNAL,
1353         DEVICED_CORE_PATH, NULL, G_DBUS_SIGNAL_FLAGS_NONE,
1354         booting_done_signal_subscriber, NULL, NULL);
1355     if (id == 0) {
1356         D("failed to subscribe to the booting done signal\n");
1357         goto bootdone_out;
1358     }
1359
1360     D("wait for the booting done signal\n");
1361     g_main_loop_run(g_mainloop);
1362
1363     g_dbus_connection_signal_unsubscribe(connection, id);
1364
1365 bootdone_out:
1366     if (g_mainloop != NULL) {
1367         g_main_loop_unref(g_mainloop);
1368     }
1369     if (connection != NULL) {
1370         g_object_unref(connection);
1371     }
1372     D("exit the bootdone_cb thread\n");
1373
1374     return NULL;
1375 }
1376
1377 void register_bootdone_cb()
1378 {
1379     sdb_thread_t t;
1380     if (sdb_thread_create(&t, bootdone_cb, NULL)) {
1381         D("can not create a service thread to check the booting done\n");
1382         return;
1383     }
1384     D("created the bootdone_cb thread\n");
1385 }
1386
1387 static int sdbd_set_groups(const char *name, int gid, struct group_info default_groups[], int default_groups_size) {
1388     gid_t *group_ids = NULL;
1389     int ngroups = 0;
1390     int i, j = 0;
1391     int group_match = 0;
1392     int added_group_cnt = 0;
1393
1394     getgrouplist(name, gid, NULL, &ngroups);
1395     D("group list : ngroups = %d\n", ngroups);
1396     group_ids = malloc((ngroups + default_groups_size) * sizeof(gid_t));
1397     if (group_ids == NULL) {
1398         D("failed to allocate group_ids(%zu)\n", (ngroups + default_groups_size) * sizeof(gid_t));
1399         return -1;
1400     }
1401     if (getgrouplist(name, gid, group_ids, &ngroups) == -1) {
1402         D("failed to getgrouplist(), ngroups = %d\n", ngroups);
1403         free(group_ids);
1404         return -1;
1405     }
1406     if(default_groups_size >= 1) {
1407         for (i = 0; default_groups[i].name != NULL; i++) {
1408             for (j = 0; j < ngroups; j++) {
1409                 if (group_ids[j] == default_groups[i].gid) {
1410                     group_match = 1;
1411                     break;
1412                 }
1413             }
1414             if (group_match == 0 && default_groups[i].gid != -1) {
1415                 group_ids[ngroups + added_group_cnt] = default_groups[i].gid;
1416                 added_group_cnt ++;
1417             }
1418             group_match = 0;
1419         }
1420     }
1421     if (setgroups(ngroups+added_group_cnt, group_ids) != 0) {
1422         D("failed to setgroups().\n");
1423         free(group_ids);
1424         return -1;
1425     }
1426
1427     free(group_ids);
1428     return 0;
1429 }
1430
1431 static int sdbd_get_user_pwd(const char* user_name, struct passwd* pwd, char* buf, size_t bufsize) {
1432     struct passwd *result = NULL;
1433     int ret = 0;
1434
1435     ret = getpwnam_r(user_name, pwd, buf, bufsize, &result);
1436     if (result == NULL) {
1437         if (ret == 0) {
1438             D("Not found passwd : username(%s)\n", user_name);
1439         } else {
1440             errno = ret;
1441             D("failed to getpwnam_r\n");
1442         }
1443         return -1;
1444     }
1445
1446     return 0;
1447 }
1448
1449 static int sdbd_get_group(const char* group_name, struct group* grp, char* buf, size_t bufsize) {
1450     struct group *result = NULL;
1451     int ret = 0;
1452
1453     ret = getgrnam_r(group_name, grp, buf, bufsize, &result);
1454     if (result == NULL) {
1455         if (ret == 0) {
1456             D("Not found group : groupname(%s)\n", group_name);
1457         } else {
1458             errno = ret;
1459             D("failed to getgrnam_r\n");
1460         }
1461         return -1;
1462     }
1463
1464     return 0;
1465 }
1466
1467 int set_sdk_user_privileges(int is_drop_capability_after_fork) {
1468     if (!is_init_sdk_userinfo) {
1469         D("failed to init sdk user information.\n");
1470         return -1;
1471     }
1472
1473     /*
1474     * If a process switches its real, effective, or saved uids from at least one being 0 to all being non-zero,
1475     * then both the permitted and effective capabilities are cleared.
1476     */
1477     if(is_drop_capability_after_fork) {
1478
1479         if (setuid(g_root_user_id) != 0) {
1480             D("set root user id failed (errno: %d)\n", errno);
1481             return -1;
1482         }
1483     }
1484
1485     if (sdbd_set_groups(SDK_USER_NAME, g_sdk_group_id, g_default_groups, SDB_DEFAULT_GROUPS_CNT) < 0) {
1486         D("set groups failed (errno: %d)\n", errno);
1487         return -1;
1488     }
1489
1490     if (setgid(g_sdk_group_id) != 0) {
1491         D("set group id failed (errno: %d)\n", errno);
1492         return -1;
1493     }
1494
1495     if (setuid(g_sdk_user_id) != 0) {
1496         D("set user id failed (errno: %d)\n", errno);
1497         return -1;
1498 //        if(is_drop_capability_after_fork) {
1499 //            return -1;
1500 //        }
1501     }
1502
1503     if (chdir(g_sdk_home_dir) < 0) {
1504         D("unable to change working directory to %s\n", g_sdk_home_dir);
1505     }
1506
1507     // TODO: use pam later
1508     if (g_sdk_home_dir_env) {
1509         putenv(g_sdk_home_dir_env);
1510     }
1511
1512     return 0;
1513 }
1514
1515 int set_root_privileges() {
1516
1517     if (sdbd_set_groups(ROOT_USER_NAME, g_root_group_id, NULL, 0) < 0) {
1518         D("set root groups failed (errno: %d)\n", errno);
1519     }
1520
1521     if (setgid(g_root_group_id) != 0) {
1522         D("set root group id failed (errno: %d)\n", errno);
1523     }
1524
1525     if (setuid(g_root_user_id) != 0) {
1526         D("set root user id failed (errno: %d)\n", errno);
1527     }
1528
1529     if (chdir(g_root_home_dir) < 0) {
1530         D("unable to change root working directory to %s\n", g_sdk_home_dir);
1531     }
1532
1533     // TODO: use pam later
1534     if (g_root_home_dir_env) {
1535         putenv(g_root_home_dir_env);
1536     }
1537
1538     return 0;
1539 }
1540
1541 #define SDB_PW_GR_DEFAULT_SIZE  (16*1024)
1542 static long get_passwd_bufsize() {
1543     long bufsize = 0;
1544
1545     bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
1546     if(bufsize < 0) {
1547         bufsize = SDB_PW_GR_DEFAULT_SIZE;
1548     }
1549
1550     return bufsize;
1551 }
1552
1553 static long get_group_bufsize() {
1554     long bufsize = 0;
1555
1556     bufsize = sysconf(_SC_GETGR_R_SIZE_MAX);
1557     if(bufsize < 0) {
1558         bufsize = SDB_PW_GR_DEFAULT_SIZE;
1559     }
1560
1561     return bufsize;
1562 }
1563
1564 static int init_sdb_default_groups() {
1565     struct group grp;
1566     char *buf = NULL;
1567     long bufsize = 0;
1568     int i = 0;
1569
1570     bufsize = get_group_bufsize();
1571     buf = malloc(bufsize);
1572     if (buf == NULL) {
1573         D("failed to allocate gruop buf(%ld)\n", bufsize);
1574         return -1;
1575     }
1576
1577     for (i = 0; g_default_groups[i].name != NULL; i++) {
1578         memset(buf, 0, bufsize);
1579         if (sdbd_get_group(g_default_groups[i].name, &grp, buf, bufsize) == 0) {
1580             g_default_groups[i].gid = grp.gr_gid;
1581         } else {
1582             D("failed get group info.(errno: %d)\n", errno);
1583         }
1584     }
1585
1586     free(buf);
1587     return 0;
1588 }
1589
1590 static void set_static_root_userinfo() {
1591     g_root_user_id = STATIC_ROOT_USER_ID;
1592     g_root_group_id = STATIC_ROOT_GROUP_ID;
1593     g_root_home_dir = STATIC_ROOT_HOME_DIR;
1594 }
1595
1596 static void set_static_sdk_userinfo() {
1597     g_sdk_user_id = STATIC_SDK_USER_ID;
1598     g_sdk_group_id = STATIC_SDK_GROUP_ID;
1599     g_sdk_home_dir = STATIC_SDK_HOME_DIR;
1600 }
1601
1602 static int init_root_userinfo() {
1603     struct passwd pwd;
1604     char *buf = NULL;
1605     long bufsize = 0;
1606
1607     bufsize = get_passwd_bufsize();
1608     buf = malloc(bufsize);
1609     if (buf == NULL) {
1610         D("failed to allocate passwd buf(%ld)\n", bufsize);
1611         set_static_root_userinfo();
1612     } else {
1613         if (sdbd_get_user_pwd(ROOT_USER_NAME, &pwd, buf, bufsize) < 0) {
1614             D("failed to get root user passwd info.(errno: %d)\n", errno);
1615             set_static_root_userinfo();
1616         } else {
1617             D("username=%s, uid=%d, gid=%d, dir=%s\n", pwd.pw_name, pwd.pw_uid, pwd.pw_gid, pwd.pw_dir);
1618
1619             g_root_user_id = pwd.pw_uid;
1620             g_root_group_id = pwd.pw_gid;
1621             g_root_home_dir = strdup(pwd.pw_dir);
1622         }
1623         free(buf);
1624     }
1625
1626     int env_size = strlen("HOME=") + strlen(g_root_home_dir) + 1;
1627     g_root_home_dir_env = malloc(env_size);
1628     if(g_root_home_dir_env == NULL) {
1629         D("failed to allocate for home dir env string\n");
1630     } else {
1631         snprintf(g_root_home_dir_env, env_size, "HOME=%s", g_root_home_dir);
1632     }
1633
1634     return 0;
1635 }
1636
1637 static int init_sdk_userinfo() {
1638     struct passwd pwd;
1639     char *buf = NULL;
1640     long bufsize = 0;
1641
1642     if (is_init_sdk_userinfo) {
1643         return 0;
1644     }
1645
1646     if (init_sdb_default_groups() < 0) {
1647         D("failed to initialize default groups.\n");
1648     }
1649
1650     bufsize = get_passwd_bufsize();
1651     buf = malloc(bufsize);
1652     if (buf == NULL) {
1653         D("failed to allocate passwd buf(%ld)\n", bufsize);
1654         set_static_sdk_userinfo();
1655     } else {
1656         if (sdbd_get_user_pwd(SDK_USER_NAME, &pwd, buf, bufsize) < 0) {
1657             D("get user passwd info.(errno: %d)\n", errno);
1658             set_static_sdk_userinfo();
1659         } else {
1660             D("username=%s, uid=%d, gid=%d, dir=%s\n", pwd.pw_name, pwd.pw_uid, pwd.pw_gid, pwd.pw_dir);
1661
1662             g_sdk_user_id = pwd.pw_uid;
1663             g_sdk_group_id = pwd.pw_gid;
1664             g_sdk_home_dir = strdup(pwd.pw_dir);
1665         }
1666         free(buf);
1667     }
1668
1669     int env_size = strlen("HOME=") + strlen(g_sdk_home_dir) + 1;
1670     g_sdk_home_dir_env = malloc(env_size);
1671     if(g_sdk_home_dir_env == NULL) {
1672         D("failed to allocate for home dir env string\n");
1673     } else {
1674         snprintf(g_sdk_home_dir_env, env_size, "HOME=%s", g_sdk_home_dir);
1675     }
1676
1677     is_init_sdk_userinfo = 1;
1678     return 0;
1679 }
1680
1681 static int safe_system(char *cmd, char *argv[], char *envp[]) {
1682     pid_t pid;
1683     int status;
1684
1685     pid = fork();
1686     switch (pid) {
1687         case -1:
1688             return -1;
1689         case 0:
1690             execve(cmd, argv, envp);
1691             D("- exec '%s' failed: (errno:%d) -\n", cmd, errno);
1692             exit(-1);
1693         default:
1694             for (;;) {
1695                 pid_t p = waitpid(pid, &status, 0);
1696                 if (p == pid) {
1697                     break;
1698                 }
1699             }
1700     }
1701     return 0;
1702 }
1703
1704 static void init_sdk_requirements() {
1705     struct stat st;
1706
1707     // set env variable for temporary
1708     // TODO: should use pam instead later!!
1709     putenv("TERM=linux");
1710     putenv("HOME=/root");
1711
1712     init_sdk_userinfo();
1713     init_root_userinfo();
1714
1715     if (g_sdk_home_dir != NULL && stat(g_sdk_home_dir, &st) == 0) {
1716         if (st.st_uid != g_sdk_user_id || st.st_gid != g_sdk_group_id) {
1717             char* cmd = "/usr/bin/chown";
1718             char params[128];
1719             char* envp[128];
1720             int envp_cnt = 0;
1721             int i = 0;
1722
1723             envp[envp_cnt++] = g_strdup("TERM=linux");
1724             envp[envp_cnt++] = g_strdup("DISPLAY=:0");
1725             envp[envp_cnt] = NULL;
1726
1727             snprintf(params, sizeof(params), "%s %s:%s %s -R", cmd, SDK_USER_NAME, SDK_USER_NAME, g_sdk_home_dir);
1728
1729             char* args[] = {
1730                 cmd,
1731                 params,
1732                 NULL,
1733             };
1734             if (safe_system(cmd, args, envp) < 0) {
1735                 D("failed to change ownership to sdk user to %s\n", g_sdk_home_dir);
1736             }
1737
1738             /* free environment variables */
1739             if (envp_cnt > 0) {
1740                 for (i = 0; i < envp_cnt; i++) {
1741                     if (envp[i]) {
1742                         g_free(envp[i]);
1743                     }
1744                 }
1745             }
1746         }
1747     }
1748
1749     if (is_emulator()) {
1750         register_bootdone_cb();
1751     }
1752 }
1753
1754 static void init_capabilities(void) {
1755     int ret = -1;
1756     char *value = NULL;
1757
1758     memset(&g_capabilities, 0, sizeof(g_capabilities));
1759
1760     // CPU Architecture of model
1761     ret = system_info_get_platform_string("http://tizen.org/feature/platform.core.cpu.arch", &value);
1762     if (ret != SYSTEM_INFO_ERROR_NONE) {
1763         snprintf(g_capabilities.cpu_arch, sizeof(g_capabilities.cpu_arch),
1764                     "%s", UNKNOWN);
1765         D("fail to get the CPU architecture of model:%d\n", errno);
1766     } else {
1767         snprintf(g_capabilities.cpu_arch, sizeof(g_capabilities.cpu_arch),
1768                     "%s", value);
1769         if (value != NULL) {
1770             free(value);
1771         }
1772     }
1773
1774
1775     // Secure protocol support
1776     if(!request_capability_to_plugin(CAPABILITY_SECURE, g_capabilities.secure_protocol,
1777                             sizeof(g_capabilities.secure_protocol))) {
1778         D("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_SECURE);
1779         snprintf(g_capabilities.secure_protocol, sizeof(g_capabilities.secure_protocol),
1780                     "%s", DISABLED);
1781     }
1782
1783
1784     // Interactive shell support
1785     if(!request_capability_to_plugin(CAPABILITY_INTER_SHELL, g_capabilities.intershell_support,
1786                             sizeof(g_capabilities.intershell_support))) {
1787         D("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_INTER_SHELL);
1788         snprintf(g_capabilities.intershell_support, sizeof(g_capabilities.intershell_support),
1789                     "%s", DISABLED);
1790     }
1791
1792
1793     // File push/pull support
1794     if(!request_capability_to_plugin(CAPABILITY_FILESYNC, g_capabilities.filesync_support,
1795                             sizeof(g_capabilities.filesync_support))) {
1796         D("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_FILESYNC);
1797         snprintf(g_capabilities.filesync_support, sizeof(g_capabilities.filesync_support),
1798                     "%s", DISABLED);
1799     }
1800
1801
1802     // USB protocol support
1803     if(!request_capability_to_plugin(CAPABILITY_USB_PROTOCOL, g_capabilities.usbproto_support,
1804                             sizeof(g_capabilities.usbproto_support))) {
1805         D("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_USB_PROTOCOL);
1806         snprintf(g_capabilities.usbproto_support, sizeof(g_capabilities.usbproto_support),
1807                     "%s", DISABLED);
1808     }
1809
1810
1811     // Socket protocol support
1812     if(!request_capability_to_plugin(CAPABILITY_SOCK_PROTOCOL, g_capabilities.sockproto_support,
1813                             sizeof(g_capabilities.sockproto_support))) {
1814         D("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_SOCK_PROTOCOL);
1815         snprintf(g_capabilities.sockproto_support, sizeof(g_capabilities.sockproto_support),
1816                     "%s", DISABLED);
1817     }
1818
1819     // Sdbd root permission
1820     snprintf(g_capabilities.root_permission, sizeof(g_capabilities.root_permission),
1821                 "%s", DISABLED);
1822
1823     // Root command support
1824     if(!request_capability_to_plugin(CAPABILITY_ROOT_ONOFF, g_capabilities.rootonoff_support,
1825                             sizeof(g_capabilities.rootonoff_support))) {
1826         D("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_ROOT_ONOFF);
1827         snprintf(g_capabilities.rootonoff_support, sizeof(g_capabilities.rootonoff_support),
1828                     "%s", DISABLED);
1829     }
1830
1831
1832     // Encryption support
1833     if(!request_capability_to_plugin(CAPABILITY_ENCRYPTION, g_capabilities.encryption_support,
1834                             sizeof(g_capabilities.encryption_support))) {
1835         D("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_ENCRYPTION);
1836         snprintf(g_capabilities.encryption_support, sizeof(g_capabilities.encryption_support),
1837                     "%s", DISABLED);
1838     }
1839
1840
1841     // Zone support
1842     ret = is_container_enabled();
1843     snprintf(g_capabilities.zone_support, sizeof(g_capabilities.zone_support),
1844                 "%s", ret == 1 ? ENABLED : DISABLED);
1845
1846     // Multi-User support
1847     // XXX: There is no clear way to determine whether multi-user support.
1848     // Since TZ_SYS_DEFAULT_USER is set to "owner" for multi-user support,
1849     // guess whether multiuser support through that information.
1850     const char* sys_default_user = tzplatform_getenv(TZ_SYS_DEFAULT_USER);
1851     if (sys_default_user != NULL && !strcmp(sys_default_user, "owner")) {
1852         snprintf(g_capabilities.multiuser_support, sizeof(g_capabilities.multiuser_support),
1853                     "%s", ENABLED);
1854     } else {
1855         snprintf(g_capabilities.multiuser_support, sizeof(g_capabilities.multiuser_support),
1856                     "%s", DISABLED);
1857     }
1858
1859     // Window size synchronization support
1860     snprintf(g_capabilities.syncwinsz_support, sizeof(g_capabilities.syncwinsz_support),
1861                 "%s", ENABLED);
1862
1863     // SDK Tool path
1864     if (SDK_TOOL_PATH == NULL) {
1865         D("fail to get SDK tool path.\n");
1866         snprintf(g_capabilities.sdk_toolpath, sizeof(g_capabilities.sdk_toolpath),
1867                     "%s", UNKNOWN);
1868     } else {
1869         snprintf(g_capabilities.sdk_toolpath, sizeof(g_capabilities.sdk_toolpath),
1870                     "%s", SDK_TOOL_PATH);
1871     }
1872
1873     // Profile name
1874     ret = system_info_get_platform_string("http://tizen.org/feature/profile", &value);
1875     if (ret != SYSTEM_INFO_ERROR_NONE) {
1876         snprintf(g_capabilities.profile_name, sizeof(g_capabilities.profile_name),
1877                     "%s", UNKNOWN);
1878         D("fail to get profile name:%d\n", errno);
1879     } else {
1880         snprintf(g_capabilities.profile_name, sizeof(g_capabilities.profile_name),
1881                     "%s", value);
1882         if (value != NULL) {
1883             free(value);
1884         }
1885     }
1886
1887
1888     // Vendor name
1889     ret = system_info_get_platform_string("http://tizen.org/system/manufacturer", &value);
1890     if (ret != SYSTEM_INFO_ERROR_NONE) {
1891         snprintf(g_capabilities.vendor_name, sizeof(g_capabilities.vendor_name),
1892                     "%s", UNKNOWN);
1893         D("fail to get the Vendor name:%d\n", errno);
1894     } else {
1895         snprintf(g_capabilities.vendor_name, sizeof(g_capabilities.vendor_name),
1896                     "%s", value);
1897         if (value != NULL) {
1898             free(value);
1899         }
1900     }
1901
1902
1903     // Target name of the launch possible
1904     if(!request_capability_to_plugin(CAPABILITY_CAN_LAUNCH, g_capabilities.can_launch,
1905                             sizeof(g_capabilities.can_launch))) {
1906         D("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_CAN_LAUNCH);
1907         snprintf(g_capabilities.can_launch, sizeof(g_capabilities.can_launch),
1908                     "%s", UNKNOWN);
1909     }
1910
1911
1912     // Device name
1913     value = vconf_get_str(VCONFKEY_SETAPPL_DEVICE_NAME_STR);
1914     if(value) {
1915         snprintf(g_capabilities.device_name, sizeof(g_capabilities.device_name),
1916                 "%s", value);
1917         if (value != NULL) {
1918             free(value);
1919         }
1920     } else {
1921         snprintf(g_capabilities.device_name, sizeof(g_capabilities.device_name),
1922                 "%s", UNKNOWN);
1923         D("fail to get the Device name:%d\n", errno);
1924     }
1925
1926
1927     // Platform version
1928     ret = system_info_get_platform_string("http://tizen.org/feature/platform.version", &value);
1929     if (ret != SYSTEM_INFO_ERROR_NONE) {
1930         snprintf(g_capabilities.platform_version, sizeof(g_capabilities.platform_version),
1931                     "%s", UNKNOWN);
1932         D("fail to get platform version:%d\n", errno);
1933     } else {
1934         snprintf(g_capabilities.platform_version, sizeof(g_capabilities.platform_version),
1935                     "%s", value);
1936         if (value != NULL) {
1937             free(value);
1938         }
1939     }
1940
1941
1942     // Product version
1943     if(!request_capability_to_plugin(CAPABILITY_PRODUCT_VER, g_capabilities.product_version,
1944                             sizeof(g_capabilities.product_version))) {
1945         D("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_PRODUCT_VER);
1946         snprintf(g_capabilities.product_version, sizeof(g_capabilities.product_version),
1947                     "%s", UNKNOWN);
1948     }
1949
1950
1951     // Sdbd version
1952     snprintf(g_capabilities.sdbd_version, sizeof(g_capabilities.sdbd_version),
1953                 "%d.%d.%d", SDB_VERSION_MAJOR, SDB_VERSION_MINOR, SDB_VERSION_PATCH);
1954
1955
1956     // Sdbd plugin version
1957     if(!request_capability_to_plugin(CAPABILITY_PLUGIN_VER, g_capabilities.sdbd_plugin_version,
1958                             sizeof(g_capabilities.sdbd_plugin_version))) {
1959         D("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_PLUGIN_VER);
1960         snprintf(g_capabilities.sdbd_plugin_version, sizeof(g_capabilities.sdbd_plugin_version),
1961                     "%s", UNKNOWN);
1962     }
1963
1964
1965     // sdbd log enable
1966     if(!request_capability_to_plugin(CAPABILITY_LOG_ENABLE, g_capabilities.log_enable,
1967                                sizeof(g_capabilities.log_enable))) {
1968            D("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_LOG_ENABLE);
1969            snprintf(g_capabilities.log_enable, sizeof(g_capabilities.log_enable),
1970                        "%s", DISABLED);
1971     }
1972
1973     // sdbd log path
1974     if(!request_capability_to_plugin(CAPABILITY_LOG_PATH, g_capabilities.log_path,
1975                                sizeof(g_capabilities.log_path))) {
1976            D("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_LOG_PATH);
1977            snprintf(g_capabilities.log_path, sizeof(g_capabilities.log_path),
1978                        "%s", UNKNOWN);
1979     }
1980
1981     // Application command support
1982     if(!request_capability_to_plugin(CAPABILITY_APPCMD, g_capabilities.appcmd_support,
1983                                sizeof(g_capabilities.appcmd_support))) {
1984            D("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_APPCMD);
1985            snprintf(g_capabilities.appcmd_support, sizeof(g_capabilities.appcmd_support),
1986                        "%s", UNKNOWN);
1987     }
1988
1989     // appid2pid support
1990     ret = is_appid2pid_supported();
1991     snprintf(g_capabilities.appid2pid_support, sizeof(g_capabilities.appid2pid_support),
1992                 "%s", ret == 1 ? ENABLED : DISABLED);
1993
1994     // pkgcmd debug mode support
1995     if(!request_capability_to_plugin(CAPABILITY_DEBUGMODE, g_capabilities.pkgcmd_debugmode,
1996                 sizeof(g_capabilities.pkgcmd_debugmode))) {
1997         D("failed to request. (%d:%d) \n", PLUGIN_SYNC_CMD_CAPABILITY, CAPABILITY_DEBUGMODE);
1998         snprintf(g_capabilities.pkgcmd_debugmode, sizeof(g_capabilities.pkgcmd_debugmode),
1999                 "%s", ENABLED);
2000     }
2001
2002     // Capability version
2003     snprintf(g_capabilities.sdbd_cap_version, sizeof(g_capabilities.sdbd_cap_version),
2004                 "%d.%d", SDBD_CAP_VERSION_MAJOR, SDBD_CAP_VERSION_MINOR);
2005 }
2006
2007 static int is_support_usbproto()
2008 {
2009     return (!strncmp(g_capabilities.usbproto_support, PLUGIN_RET_ENABLED, strlen(PLUGIN_RET_ENABLED)));
2010 }
2011
2012 static int is_support_sockproto()
2013 {
2014     return (!strncmp(g_capabilities.sockproto_support, PLUGIN_RET_ENABLED, strlen(PLUGIN_RET_ENABLED)));
2015 }
2016
2017 #define EMULATOR_MODEL_NAME     "Emulator"
2018 static void check_emulator_or_device()
2019 {
2020     char model_name[256]={0,};
2021     int ret = -1;
2022
2023     // Get the model name from model_config.xml
2024     ret = get_device_name(model_name, sizeof model_name);
2025     if (ret == 0) {
2026         if(!strncmp(model_name, EMULATOR_MODEL_NAME, sizeof(EMULATOR_MODEL_NAME))){
2027             g_is_emulator = 1;
2028             D("This target type is Emulator\n");
2029         } else {
2030             g_is_emulator = 0;
2031             D("This target type is Device\n");
2032         }
2033     } else {
2034         g_is_emulator = -1;
2035         D("failed to get the model name.\n");
2036     }
2037 }
2038
2039 static void fork_prepare_handler(void)
2040 {
2041     sdb_mutex_lock(&D_lock);
2042 }
2043
2044 static void fork_parent_handler(void)
2045 {
2046     sdb_mutex_unlock(&D_lock);
2047 }
2048
2049 static void fork_child_handler(void)
2050 {
2051     sdb_mutex_unlock(&D_lock);
2052 }
2053
2054 int sdb_main(int server_port)
2055 {
2056     check_emulator_or_device();
2057
2058     load_sdbd_plugin();
2059
2060     init_capabilities();
2061
2062     sdb_trace_init();
2063     start_device_log();
2064
2065     init_drop_privileges();
2066     init_sdk_requirements();
2067     if (!request_validity_to_plugin(PLUGIN_SYNC_CMD_VERIFY_LAUNCH, NULL)) {
2068         D("sdbd should be launched in develop mode.\n");
2069         return -1;
2070     }
2071
2072     umask(000);
2073
2074     pthread_atfork(fork_prepare_handler, fork_parent_handler, fork_child_handler);
2075
2076     atexit(sdb_cleanup);
2077 #if defined(HAVE_FORKEXEC)
2078     // No SIGCHLD. Let the service subproc handle its children.
2079     signal(SIGPIPE, SIG_IGN);
2080 #endif
2081
2082     init_transport_registration();
2083
2084     /* don't listen on a port (default 5037) if running in secure mode */
2085     /* don't run as root if we are running in secure mode */
2086
2087     if (should_drop_privileges()) {
2088 # if 0
2089         struct __user_cap_header_struct header;
2090         struct __user_cap_data_struct cap;
2091
2092         if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) != 0) {
2093             exit(1);
2094         }
2095         /* add extra groups:
2096         ** SID_TTY to access /dev/ptmx
2097         */
2098         gid_t groups[] = { SID_TTY, SID_APP_LOGGING, SID_SYS_LOGGING };
2099         if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) {
2100             exit(1);
2101         }
2102         /* then switch user and group to "developer" */
2103         if (setgid(GID_DEVELOPER) != 0) {
2104             fprintf(stderr, "set group id failed errno: %d\n", errno);
2105             exit(1);
2106         }
2107         if (setuid(SID_DEVELOPER) != 0) {
2108             fprintf(stderr, "set user id failed errno: %d\n", errno);
2109             exit(1);
2110         }
2111
2112         /* set CAP_SYS_BOOT capability, so "sdb reboot" will succeed */
2113         header.version = _LINUX_CAPABILITY_VERSION;
2114         header.pid = 0;
2115         cap.effective = cap.permitted = (1 << CAP_SYS_BOOT);
2116         cap.inheritable = 0;
2117         capset(&header, &cap);
2118 #endif
2119         D("Local port disabled\n");
2120     } else {
2121         char local_name[30];
2122         build_local_name(local_name, sizeof(local_name), server_port);
2123         if(install_listener(local_name, "*smartsocket*", NULL)) {
2124             exit(1);
2125         }
2126     }
2127
2128     /* choose the usb gadget backend */
2129     if (access(USB_NODE_FILE, F_OK) == 0) {
2130         /* legacy kernel-based sdb gadget */
2131         usb_init =    &linux_usb_init;
2132         usb_cleanup = &linux_usb_cleanup;
2133         usb_write =   &linux_usb_write;
2134         usb_read =    &linux_usb_read;
2135         usb_close =   &linux_usb_close;
2136         usb_kick =    &linux_usb_kick;
2137     } else {
2138         /* functionfs based gadget */
2139         usb_init =    &ffs_usb_init;
2140         usb_cleanup = &ffs_usb_cleanup;
2141         usb_write =   &ffs_usb_write;
2142         usb_read =    &ffs_usb_read;
2143         usb_close =   &ffs_usb_close;
2144         usb_kick =    &ffs_usb_kick;
2145     }
2146
2147     if (is_support_usbproto()) {
2148         // listen on USB
2149         usb_init();
2150     }
2151     if (is_support_sockproto()) {
2152         /* by default don't listen on local transport but
2153          * listen if suitable command line argument has been provided */
2154         if (sdbd_commandline_args.sdbd_port >= 0) {
2155             local_init(sdbd_commandline_args.sdbd_port);
2156         } else {
2157             local_init(DEFAULT_SDB_LOCAL_TRANSPORT_PORT);
2158         }
2159     }
2160
2161 #if 0 /* tizen specific */
2162     D("sdb_main(): pre init_jdwp()\n");
2163     init_jdwp();
2164     D("sdb_main(): post init_jdwp()\n");
2165 #endif
2166
2167     D("Event loop starting\n");
2168
2169     fdevent_loop();
2170
2171     if (is_support_usbproto()) {
2172         usb_cleanup();
2173     }
2174
2175     return 0;
2176 }
2177
2178 int copy_packet(apacket* dest, apacket* src) {
2179
2180     if(dest == NULL) {
2181         D("dest packet is NULL\n");
2182         return -1;
2183     }
2184
2185     if(src == NULL) {
2186         D("src packet is NULL\n");
2187         return -1;
2188     }
2189
2190     dest->next = src->next;
2191     dest->ptr = src->ptr;
2192     dest->len = src->len;
2193
2194     int data_length = src->msg.data_length;
2195     if(data_length > MAX_PAYLOAD) {
2196         data_length = MAX_PAYLOAD;
2197     }
2198     memcpy(&(dest->msg), &(src->msg), sizeof(amessage) + data_length);
2199
2200     return 0;
2201 }
2202
2203 int handle_host_request(char *service, transport_type ttype, char* serial, int reply_fd, asocket *s)
2204 {
2205     atransport *transport = NULL;
2206     char buf[4096];
2207
2208     if(!strcmp(service, "kill")) {
2209         fprintf(stderr,"sdb server killed by remote request\n");
2210         fflush(stdout);
2211         sdb_write(reply_fd, "OKAY", 4);
2212         if (is_support_usbproto()) {
2213             usb_cleanup();
2214         }
2215         exit(0);
2216     }
2217
2218     if(!strncmp(service,"forward:",8) || !strncmp(service,"killforward:",12)) {
2219         char *local, *remote, *err;
2220         int r;
2221         atransport *transport;
2222
2223         int createForward = strncmp(service,"kill",4);
2224
2225         local = service + (createForward ? 8 : 12);
2226         remote = strchr(local,';');
2227         if(remote == 0) {
2228             sendfailmsg(reply_fd, "malformed forward spec");
2229             return 0;
2230         }
2231
2232         *remote++ = 0;
2233         if((local[0] == 0) || (remote[0] == 0) || (remote[0] == '*')){
2234             sendfailmsg(reply_fd, "malformed forward spec");
2235             return 0;
2236         }
2237
2238         transport = acquire_one_transport(CS_ANY, ttype, serial, &err);
2239         if (!transport) {
2240             sendfailmsg(reply_fd, err);
2241             return 0;
2242         }
2243
2244         if (createForward) {
2245             r = install_listener(local, remote, transport);
2246         } else {
2247             r = remove_listener(local, remote, transport);
2248         }
2249         if(r == 0) {
2250                 /* 1st OKAY is connect, 2nd OKAY is status */
2251             writex(reply_fd, "OKAYOKAY", 8);
2252             return 0;
2253         }
2254
2255         if (createForward) {
2256             sendfailmsg(reply_fd, (r == -1) ? "cannot rebind smartsocket" : "cannot bind socket");
2257         } else {
2258             sendfailmsg(reply_fd, "cannot remove listener");
2259         }
2260         return 0;
2261     }
2262
2263     if(!strncmp(service,"get-state",strlen("get-state"))) {
2264         transport = acquire_one_transport(CS_ANY, ttype, serial, NULL);
2265         char *state = connection_state_name(transport);
2266         snprintf(buf, sizeof buf, "OKAY%04x%s",(unsigned)strlen(state),state);
2267         writex(reply_fd, buf, strlen(buf));
2268         return 0;
2269     }
2270     return -1;
2271 }
2272
2273 int recovery_mode = 0;
2274
2275 int main(int argc, char **argv)
2276 {
2277     /* If sdbd runs inside the emulator this will enable sdb tracing via
2278      * sdb-debug qemud service in the emulator. */
2279 #if 0 /* tizen specific */
2280     sdb_qemu_trace_init();
2281     if((argc > 1) && (!strcmp(argv[1],"recovery"))) {
2282         sdb_device_banner = "recovery";
2283         recovery_mode = 1;
2284     }
2285 #endif
2286
2287     apply_sdbd_commandline_defaults(&sdbd_commandline_args);
2288     int parse_ret = parse_sdbd_commandline(&sdbd_commandline_args, argc, argv);
2289
2290     // TODO: Add detailed error messages
2291     // TODO: Add individual messages for help and usage
2292     if(parse_ret != SDBD_COMMANDLINE_SUCCESS) {
2293         if (parse_ret == SDBD_COMMANDLINE_HELP
2294                 || parse_ret == SDBD_COMMANDLINE_USAGE) {
2295             // User requested help or usage
2296             print_sdbd_usage_message(stdout);
2297             return EXIT_SUCCESS;
2298         }
2299
2300         // Print usage message because of invalid options
2301         print_sdbd_usage_message(stderr);
2302         return EXIT_FAILURE;
2303     }
2304
2305     if (daemonize() < 0)
2306         fatal("daemonize() failed: errno:%d", errno);
2307
2308     D("Handling main()\n");
2309
2310     //sdbd will never die on emulator!
2311     signal(SIGTERM, handle_sig_term); /* tizen specific */
2312     return sdb_main(DEFAULT_SDB_PORT);
2313 }
2314