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