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