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