ecs: change host address data type to INADDR_ANY
[sdk/emulator/qemu.git] / tizen / src / util / net_helper.c
1 /*
2  * Net helper
3  *
4  * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
5  *
6  * Contact:
7  *  MunKyu Im       <munkyu.im@samsung.com>
8  *  Jinhyung Choi   <jinh0.choi@samsung.com>
9  *  SeokYeon Hwnag  <syeon.hwang@samsung.com>
10  *  Sangho Park     <sangho.p@samsung.com>
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
25  *
26  * Contributors:
27  * - S-Core Co., Ltd
28  *
29  */
30
31 #include "net_helper.h"
32
33 #include "qemu/osdep.h"
34 #include "qemu/sockets.h"
35 #include "net/slirp.h"
36 #include "block/nbd.h"
37 #include "qemu/error-report.h"
38
39 #include "emulator.h"
40 #include "emulator_common.h"
41 #include "emul_state.h"
42
43 #include "hw/virtio/maru_virtio_input.h"
44 #include "hw/maru_pm.h"
45 #include "ecs/ecs.h"
46 #include "new_debug_ch.h"
47
48 DECLARE_DEBUG_CHANNEL(net_helper);
49
50 #define BUF_SIZE 64
51 #define MAX_TRIAL 20
52 #define MAX_USER_NAME_LEN 36
53
54 int emul_vm_base_socket;
55 static bool sdb_daemon_is_initialized = false;
56 static QemuThread thread_id;
57
58 int inet_strtoip(const char*  str, uint32_t  *ip)
59 {
60     int  comp[4];
61
62     if (sscanf(str, "%d.%d.%d.%d", &comp[0], &comp[1], &comp[2], &comp[3]) != 4)
63         return -1;
64
65     if ((unsigned)comp[0] >= 256 ||
66             (unsigned)comp[1] >= 256 ||
67             (unsigned)comp[2] >= 256 ||
68             (unsigned)comp[3] >= 256)
69         return -1;
70
71     *ip = (uint32_t)((comp[0] << 24) | (comp[1] << 16) |
72             (comp[2] << 8)  |  comp[3]);
73     return 0;
74 }
75
76 int check_port_bind_listen(uint32_t port)
77 {
78     struct sockaddr_in addr;
79     int ret = -1;
80     addr.sin_family = AF_INET;
81     addr.sin_port = htons(port);
82     addr.sin_addr.s_addr = INADDR_ANY;
83
84     ret = qemu_socket(PF_INET, SOCK_STREAM, 0);
85     if (ret < 0) {
86         LOG_SEVERE("socket creation failed.\n");
87         return -1;
88     }
89
90     qemu_set_nonblock(ret);
91
92     if (socket_set_fast_reuse(ret) != 0) {
93         LOG_SEVERE("It cannot be reach here.\n");
94         closesocket(ret);
95         return -1;
96     }
97
98     if (bind(ret, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
99         LOG_INFO("bind failed for port: %d, errno: %d\n", port, errno);
100         closesocket(ret);
101         return -1;
102     }
103
104     if (listen(ret, 1) != 0) {
105         LOG_SEVERE("listen failed :%s-%d\n", strerror(errno), errno);
106         closesocket(ret);
107         return -1;
108     }
109
110     return ret;
111 }
112
113 static int prepare_network_port(uint32_t base_port)
114 {
115     int ret = -1;
116
117     /* no need to redir if network is tap */
118     if (!is_netclient_tap_attached()) {
119         if (!hostfwd_try_add(0, NULL, base_port + SDB_TCP_INDEX,
120                 NULL, SDB_GUEST_PORT)) {
121             LOG_INFO("TCP port %"PRIu32" is aleady occupied",
122                     base_port + SDB_TCP_INDEX);
123
124             return -1;
125         }
126
127         if (!hostfwd_try_add(0, NULL, base_port + GDB_TCP_INDEX,
128                 NULL, GDB_GUEST_PORT)) {
129             LOG_INFO("TCP port %"PRIu32" is aleady occupied",
130                     base_port + GDB_TCP_INDEX);
131             hostfwd_try_remove(0, NULL, base_port + SDB_TCP_INDEX);
132
133             return -1;
134         }
135     }
136
137     if ((ret = check_port_bind_listen(base_port + ECS_TCP_INDEX)) < 0) {
138         LOG_INFO("TCP port %"PRIu32" is aleady occupied",
139                 base_port + ECS_TCP_INDEX);
140
141         if (!is_netclient_tap_attached()) {
142             hostfwd_try_remove(0, NULL, base_port + SDB_TCP_INDEX);
143             hostfwd_try_remove(0, NULL, base_port + GDB_TCP_INDEX);
144         }
145
146         return -1;
147     }
148
149     g_assert(ret >= 0);
150
151     // save ecs socket fd as global variable
152     // FIXME: should not use global variable.
153     emul_vm_base_socket = ret;
154
155     return ret;
156 }
157
158 static void start_sdb_noti_server(int server_port);
159
160 void init_sdb_and_vm_base_port(void)
161 {
162     uint32_t port = -1;
163
164     for (port = START_VM_BASE_PORT ; port < END_VM_BASE_PORT; port += 10) {
165         if (prepare_network_port(port) < 0) {
166             continue;
167         }
168
169         break;
170     }
171
172     if (port >= END_VM_BASE_PORT) {
173         error_report("It seems too many emulator instances are "
174                 "running on this machine. Aborting.");
175         exit(1);
176     }
177
178     LOG_INFO("Emulator base port is %"PRIu32".\n", port);
179
180     start_sdb_noti_server(port + SDB_UDP_NOTI_PORT_INDEX);
181
182     vm_base_port = port;
183 }
184
185 /*
186  * SDB Notification server
187  */
188
189 #define RECV_BUF_SIZE 32
190 typedef struct SDB_Noti_Server {
191     int server_fd;
192     GIOChannel *server_chan;
193     guint server_tag;
194 } SDB_Noti_Server;
195
196 typedef struct SDB_Client {
197     int port;
198     struct sockaddr_in addr;
199     char serial[RECV_BUF_SIZE];
200
201     QTAILQ_ENTRY(SDB_Client) next;
202 } SDB_Client;
203
204 static QTAILQ_HEAD(SDB_ClientHead, SDB_Client)
205 clients = QTAILQ_HEAD_INITIALIZER(clients);
206
207 static SDB_Noti_Server *current_server;
208 static QemuMutex mutex_clients;
209 static QemuMutex mutex_request;
210
211 static void remove_sdb_client(SDB_Client* client)
212 {
213     if (client == NULL) {
214         return;
215     }
216
217     qemu_mutex_lock(&mutex_clients);
218
219     QTAILQ_REMOVE(&clients, client, next);
220
221     qemu_mutex_unlock(&mutex_clients);
222
223     g_free(client);
224 }
225
226 static void send_to_sdb_client(SDB_Client* client, int state)
227 {
228     struct sockaddr_in sock_addr;
229     int s, slen = sizeof(sock_addr);
230     int serial_len = 0;
231     char buf[BUF_SIZE];
232
233     if ((s = qemu_socket(AF_INET, SOCK_STREAM, 0)) == -1){
234           LOG_INFO("socket creation error! %d\n", errno);
235           return;
236     }
237
238     memset(&sock_addr, 0, sizeof(sock_addr));
239
240     sock_addr.sin_family = AF_INET;
241     sock_addr.sin_port = htons(client->port);
242     sock_addr.sin_addr = (client->addr).sin_addr;
243
244     if (connect(s, (struct sockaddr*)&sock_addr, slen) == -1) {
245         LOG_INFO("connect error! remove this client.\n");
246         remove_sdb_client(client);
247         closesocket(s);
248         return;
249     }
250
251     memset(buf, 0, sizeof(buf));
252
253     serial_len = strlen(client->serial);
254
255     // send message "[4 digit message length]host:sync:emulator-26101:[0|1]"
256     sprintf(buf, "%04xhost:sync:%s:%01d", (serial_len + 12), client->serial, state);
257
258     LOG_INFO("send %s to client %s\n", buf, inet_ntoa(client->addr.sin_addr));
259
260     if (send(s, buf, sizeof(buf), 0) == -1)
261     {
262         LOG_INFO("send error! remove this client.\n");
263         remove_sdb_client(client);
264     }
265
266     closesocket(s);
267 }
268
269 void notify_all_sdb_clients(int state)
270 {
271     qemu_mutex_lock(&mutex_clients);
272     SDB_Client *client, *next;
273
274     QTAILQ_FOREACH_SAFE(client, &clients, next, next)
275     {
276         send_to_sdb_client(client, state);
277     }
278     qemu_mutex_unlock(&mutex_clients);
279
280 }
281
282 static void add_sdb_client(struct sockaddr_in* addr, int port, const char* serial)
283 {
284     SDB_Client *cli = NULL;
285     SDB_Client *client = NULL, *next;
286
287     if (addr == NULL) {
288         LOG_INFO("SDB_Client client's address is EMPTY.\n");
289         return;
290     } else if (serial == NULL || strlen(serial) <= 0) {
291         LOG_INFO("SDB_Client client's serial is EMPTY.\n");
292         return;
293     } else if (strlen(serial) > RECV_BUF_SIZE) {
294         LOG_INFO("SDB_Client client's serial is too long. %s\n", serial);
295         return;
296     }
297
298     qemu_mutex_lock(&mutex_clients);
299     QTAILQ_FOREACH_SAFE(cli, &clients, next, next)
300     {
301         if (!strcmp(serial, cli->serial) && !strcmp(inet_ntoa(addr->sin_addr), inet_ntoa((cli->addr).sin_addr))) {
302             LOG_INFO("Client cannot be duplicated.\n");
303             qemu_mutex_unlock(&mutex_clients);
304             return;
305         }
306     }
307     qemu_mutex_unlock(&mutex_clients);
308
309     client = g_malloc0(sizeof(SDB_Client));
310     if (NULL == client) {
311         LOG_INFO("SDB_Client allocation failed.\n");
312         return;
313     }
314
315     memcpy(&client->addr, addr, sizeof(struct sockaddr_in));
316     client->port = port;
317     strcpy(client->serial, serial);
318
319     qemu_mutex_lock(&mutex_clients);
320
321     QTAILQ_INSERT_TAIL(&clients, client, next);
322
323     qemu_mutex_unlock(&mutex_clients);
324
325     LOG_INFO("Added new sdb client. ip: %s, port: %d, serial: %s\n", inet_ntoa((client->addr).sin_addr), client->port, client->serial);
326
327     send_to_sdb_client(client, runstate_check(RUN_STATE_SUSPENDED));
328 }
329
330 static int parse_val(char* buff, unsigned char data, char* parsbuf)
331 {
332     int count = 0;
333
334     while (1) {
335         if (count > 12) {
336             return -1;
337         }
338
339         if (buff[count] == data) {
340             count++;
341             strncpy(parsbuf, buff, count);
342             return count;
343         }
344
345         count++;
346     }
347
348     return 0;
349 }
350
351 #define SDB_SERVER_PORT 26097
352 static void register_sdb_server(char* readbuf, struct sockaddr_in* client_addr)
353 {
354     int port = 0;
355     char token[] = "\n";
356     char* ret = NULL;
357     char* serial = NULL;
358
359     ret = strtok(readbuf, token);
360     if (ret == NULL) {
361         LOG_INFO("command is not found.");
362         return;
363     }
364
365     serial = strtok(NULL, token);
366     if (serial == NULL) {
367         LOG_INFO("serial is not found.");
368         return;
369     }
370
371     port = SDB_SERVER_PORT;
372
373     add_sdb_client(client_addr, port, serial);
374 }
375
376 #define PRESS     1
377 #define RELEASE   2
378 #define POWER_KEY 116
379 static void wakeup_guest(void)
380 {
381     // FIXME: Temporarily working model.
382     // It must be fixed as the way it works.
383     maru_hwkey_event(PRESS, POWER_KEY);
384     maru_hwkey_event(RELEASE, POWER_KEY);
385 }
386
387 static void suspend_lock_state(int state)
388 {
389     ecs_suspend_lock_state(state);
390 }
391
392 static void *get_user_home_path(void *args)
393 {
394     FILE *fp;
395     char user_name[MAX_USER_NAME_LEN] = { 0, } ;
396     int trial = 0;
397     int sleep_time = 500; // msec
398 #ifndef CONFIG_WIN32
399     const char *sdb_path = "../../../../../tools/sdb";
400 #else
401     const char *sdb_path = "..\\..\\..\\..\\..\\tools\\sdb.exe";
402 #endif
403     const char *bin_dir = get_bin_path();
404
405     qemu_mutex_lock(&mutex_request);
406
407     if (get_platform_default_home()) {
408         return NULL;
409     }
410 #ifndef CONFIG_WIN32
411     char *cmd_root_off = g_strdup_printf("\"%s%s\" -s emulator-%d root off 2> /dev/null",
412             bin_dir, sdb_path, get_vm_device_serial_number());
413     char *cmd_get_home = g_strdup_printf("\"%s%s\" -s emulator-%d shell id -un 2> /dev/null",
414             bin_dir, sdb_path, get_vm_device_serial_number());
415 #else
416     char *cmd_root_off = g_strdup_printf("\"%s%s\" -s emulator-%d root off 2> NUL",
417             bin_dir, sdb_path, get_vm_device_serial_number());
418     char *cmd_get_home = g_strdup_printf("\"%s%s\" -s emulator-%d shell id -un 2> NUL",
419             bin_dir, sdb_path, get_vm_device_serial_number());
420 #endif
421     //FIXME: (sdb) cannot check sdb root status
422     fp = popen(cmd_root_off, "r");
423     if (fp == NULL) {
424         LOG_WARNING("Failed to run command\n");
425         g_free(cmd_root_off);
426         return NULL;
427     }
428     g_free(cmd_root_off);
429     pclose(fp);
430     while (true) {
431         if (trial >= MAX_TRIAL) {
432             sleep_time = 2000;
433         } else {
434             trial++;
435         }
436 #ifdef CONFIG_WIN32
437         Sleep(sleep_time);
438 #else
439         usleep(sleep_time * 1000);
440 #endif
441         fp = popen(cmd_get_home, "r");
442         if (fp == NULL) {
443             LOG_WARNING("Failed to run command\n");
444             break;
445         }
446
447         if (fgets(user_name, sizeof(user_name), fp)) {
448             g_strstrip(user_name);
449             if (strlen(user_name) > 0) {
450                 char *path = g_strdup_printf("/home/%s/", user_name);
451                 set_platform_default_home(path);
452                 g_free(path);
453                 pclose(fp);
454                 break;
455             }
456         }
457
458         pclose(fp);
459     }
460     g_free(cmd_get_home);
461
462     if (!get_platform_default_home()) {
463         set_platform_default_home("/tmp/");
464     }
465
466     LOG_INFO("platform_default_user_home: %s\n", get_platform_default_home());
467
468     qemu_mutex_unlock(&mutex_request);
469
470     return NULL;
471 }
472
473 static void command_handler(char* readbuf, struct sockaddr_in* client_addr)
474 {
475     char command[RECV_BUF_SIZE];
476     memset(command, '\0', sizeof(command));
477
478     parse_val(readbuf, 0x0a, command);
479
480     LOG_TRACE("----------------------------------------\n");
481     LOG_TRACE("command:%s\n", command);
482     if (strcmp(command, "2\n" ) == 0) {
483         sdb_daemon_is_initialized = true;
484         if (!get_platform_default_home()) {
485             qemu_thread_create(&thread_id, "get_platform_default_home",
486                     get_user_home_path, NULL, QEMU_THREAD_DETACHED);
487         }
488     } else if (strcmp(command, "5\n") == 0) {
489         register_sdb_server(readbuf, client_addr);
490         set_sdb_connection(true);
491     } else if (strcmp(command, "6\n") == 0) {
492         wakeup_guest();
493     } else if (strcmp(command, "7\n") == 0) {
494         suspend_lock_state(SUSPEND_LOCK);
495     } else if (strcmp(command, "8\n") == 0) {
496         suspend_lock_state(SUSPEND_UNLOCK);
497     } else {
498         LOG_INFO("!!! unknown command : %s\n", command);
499     }
500     LOG_TRACE("========================================\n");
501 }
502
503 static void close_clients(void)
504 {
505     qemu_mutex_lock(&mutex_clients);
506     SDB_Client * client, *next;
507
508     QTAILQ_FOREACH_SAFE(client, &clients, next, next)
509     {
510         QTAILQ_REMOVE(&clients, client, next);
511
512         if (NULL != client)
513         {
514             g_free(client);
515         }
516     }
517
518     qemu_mutex_unlock(&mutex_clients);
519 }
520
521 static void close_server(void)
522 {
523     if (current_server == NULL) {
524         return;
525     }
526
527     close_clients();
528
529     if (current_server->server_fd > 0) {
530         if (current_server->server_tag) {
531             g_source_remove(current_server->server_tag);
532             current_server->server_tag = 0;
533         }
534         if (current_server->server_chan) {
535             g_io_channel_unref(current_server->server_chan);
536         }
537         closesocket(current_server->server_fd);
538     }
539
540     g_free(current_server);
541
542     qemu_mutex_destroy(&mutex_clients);
543 }
544
545 static gboolean sdb_noti_read(GIOChannel *channel, GIOCondition cond, void *opaque)
546 {
547     int recv_cnt = 0;
548     struct sockaddr_in client_addr;
549     socklen_t client_len = sizeof(client_addr);
550     char readbuf[RECV_BUF_SIZE + 1];
551     SDB_Noti_Server *server = opaque;
552
553     memset(&readbuf, 0, sizeof(readbuf));
554
555     recv_cnt = recvfrom(server->server_fd, readbuf, RECV_BUF_SIZE, 0,
556                         (struct sockaddr*) &client_addr, &client_len);
557
558     if (recv_cnt > 0) {
559         command_handler((char*)readbuf, &client_addr);
560     } else if (recv_cnt == 0) {
561         LOG_INFO("noti server recvfrom returned 0.\n");
562     } else {
563 #ifdef _WIN32
564         errno = WSAGetLastError();
565 #endif
566         LOG_TRACE("recvfrom error case (it can be from non-blocking socket): %d", errno);
567     }
568
569     return TRUE;
570 }
571
572 static int create_UDP_server(SDB_Noti_Server *server, int port)
573 {
574     struct sockaddr_in server_addr;
575     int opt = 1;
576
577     if ((server->server_fd = qemu_socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
578         LOG_INFO("create listen socket error:%d\n", errno);
579         return -1;
580     }
581
582     memset(&server_addr, '\0', sizeof(server_addr));
583     server_addr.sin_family = PF_INET;
584     server_addr.sin_addr.s_addr = INADDR_ANY;
585     server_addr.sin_port = htons(port);
586
587     qemu_set_nonblock(server->server_fd);
588
589     if (qemu_setsockopt(server->server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) {
590         LOG_INFO("setsockopt SO_REUSEADDR is failed.: %d\n", errno);
591         return -1;
592     }
593
594     if (bind(server->server_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0) {
595         LOG_INFO("sdb noti server bind error: %d", errno);
596         return -1;
597     }
598
599     return 0;
600 }
601
602 static GIOChannel *io_channel_from_socket(int fd)
603 {
604     GIOChannel *chan;
605
606     if (fd == -1) {
607         return NULL;
608     }
609
610 #ifdef _WIN32
611     chan = g_io_channel_win32_new_socket(fd);
612 #else
613     chan = g_io_channel_unix_new(fd);
614 #endif
615
616     g_io_channel_set_encoding(chan, NULL, NULL);
617     g_io_channel_set_buffered(chan, FALSE);
618
619     return chan;
620 }
621
622 static void sdb_noti_server_notify_exit(Notifier *notifier, void *data)
623 {
624     LOG_INFO("shutdown sdb notification server.\n");
625     close_server();
626 }
627
628 static Notifier sdb_noti_server_exit = { .notify = sdb_noti_server_notify_exit };
629
630 static void start_sdb_noti_server(int server_port)
631 {
632     SDB_Noti_Server *server;
633     int ret;
634
635     LOG_INFO("start sdb noti server thread.\n");
636
637     server = g_malloc0(sizeof(SDB_Noti_Server));
638     if (server == NULL) {
639         LOG_INFO("SDB Notification server allocation is failed.\n");
640         return;
641     }
642
643     ret = create_UDP_server(server, server_port);
644     if (ret < 0) {
645         LOG_INFO("failed to create UDP server\n");
646         close_server();
647         return;
648     }
649
650     qemu_mutex_init(&mutex_clients);
651     qemu_mutex_init(&mutex_request);
652
653     server->server_chan = io_channel_from_socket(server->server_fd);
654     server->server_tag = g_io_add_watch(server->server_chan, G_IO_IN, sdb_noti_read, server);
655
656     current_server = server;
657
658     LOG_INFO("success to bind port[127.0.0.1:%d/udp] for sdb noti server in host \n", server_port);
659
660     emulator_add_exit_notifier(&sdb_noti_server_exit);
661 }
662
663 bool is_sdb_daemon_initialized(void)
664 {
665     return sdb_daemon_is_initialized;
666 }