Merge "[CID-32919, 33501] Fix bug" into tizen
[platform/upstream/connman.git] / vpn / plugins / vici-client.c
1 /*
2  *
3  *  ConnMan VPN daemon
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License version 2 as
7  *  published by the Free Software Foundation.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  *
18  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <stdint.h>
24 #include <unistd.h>
25 #include <errno.h>
26
27 #include <sys/poll.h>
28 #include <sys/socket.h>
29 #include <sys/un.h>
30 #include <sys/stat.h>
31 #include <arpa/inet.h>
32
33 #include <glib.h>
34
35 #include <connman/log.h>
36 #include "ipsec.h"
37 #include "vici-client.h"
38
39 #define SOCK_FD_MIN 3
40 #define VICI_REQUEST_TIMEOUT 5000
41
42 enum vici_element {
43         VICI_END = 0,
44         VICI_SECTION_START = 1,
45         VICI_SECTION_END = 2,
46         VICI_KEY_VALUE = 3,
47         VICI_LIST_START = 4,
48         VICI_LIST_ITEM = 5,
49         VICI_LIST_END = 6,
50 };
51
52 enum vici_packet_type {
53         VICI_CMD_REQUEST = 0,
54         VICI_CMD_RESPONSE = 1,
55         VICI_CMD_UNKNOWN = 2,
56         VICI_EVENT_REGISTER = 3,
57         VICI_EVENT_UNREGISTER = 4,
58         VICI_EVENT_CONFIRM = 5,
59         VICI_EVENT_UNKNOWN = 6,
60         VICI_EVENT = 7,
61 };
62
63 static const char *vici_cmd_str[] = {
64         "load-conn",
65         "load-shared",
66         "load-cert",
67         "load-authority",
68         "unload-authority",
69         "load-key",
70         "initiate",
71         "terminate",
72         "child-updown",
73         NULL,
74 };
75
76 struct request {
77         unsigned int allocated;
78         unsigned int used;
79         unsigned int hdr_len;
80         char *sndbuf;
81         int cmd;
82         int err;
83         /* process reply */
84         unsigned int rcv_pkt_size;
85         char *rcvbuf;
86         /* davici_cb cb; */
87         void *user;
88 };
89
90 struct _VICIClient {
91         /* io data */
92         int client_sock_fd;
93         int client_watch;
94         unsigned int rcv_pkt_size;
95         char *rcvbuf;
96         GSList *request_list;
97         vici_request_reply_cb reply_cb;
98         vici_event_cb event_cb;
99         void *reply_user_data;
100         void *event_user_data;
101 };
102
103 struct _VICISection {
104         char *name;
105         GHashTable *kvs;
106         GHashTable *kvls;
107         GHashTable *subsection;
108 };
109
110 static void remove_list(gpointer data)
111 {
112         if (data == NULL)
113                 return;
114
115         g_slist_free_full((GSList *)data, g_free);
116 }
117
118 void vici_destroy_section(VICISection* section)
119 {
120         g_free(section->name);
121         g_hash_table_destroy(section->kvs);
122         g_hash_table_destroy(section->kvls);
123         g_hash_table_destroy(section->subsection);
124         g_free(section);
125 }
126
127 static void free_section(gpointer data)
128 {
129         VICISection* section = (VICISection*)data;
130         vici_destroy_section(section);
131 }
132
133 VICISection* vici_create_section(const char* name)
134 {
135         VICISection* section;
136
137         section = g_try_new0(VICISection, 1);
138         if (!section) {
139                 connman_error("Failed to create section");
140                 return NULL;
141         }
142
143         if (name)
144                 section->name = g_strdup(name);
145         section->kvs = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
146         section->kvls = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, remove_list);
147         section->subsection = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, free_section);
148         return section;
149 }
150
151 int add_subsection(const char* name, VICISection* child, VICISection* section)
152 {
153         if (section == NULL || name == NULL || child == NULL) {
154                 connman_error("invalid parameter");
155                 return -1;
156         }
157
158         g_hash_table_insert(section->subsection, g_strdup(name), child);
159         return 0;
160 }
161
162 static int add_kvl_to_section(const char* key, const char* value, VICISection* section)
163 {
164         GSList *list = NULL;
165         if (section == NULL || key == NULL || value == NULL) {
166                 connman_error("invalid parameter");
167                 return -1;
168         }
169
170         list = g_hash_table_lookup(section->kvls, key);
171         if (list == NULL)
172                 list = g_slist_alloc();
173
174         list = g_slist_prepend(list, g_strdup(value));
175         g_hash_table_replace(section->kvls, g_strdup(key), list);
176         return 0;
177 }
178
179 static int add_kv_to_section(const char* key, const char* value, VICISection* section)
180 {
181         if (section == NULL || key == NULL || value == NULL) {
182                 connman_error("invalid parameter");
183                 return -1;
184         }
185
186         g_hash_table_insert(section->kvs, g_strdup(key), g_strdup(value));
187         return 0;
188 }
189
190 static VICISection* get_subsection(VICISection* section, const char* name)
191 {
192         VICISection* sub = g_hash_table_lookup(section->subsection, name);
193         if (sub == NULL) {
194                 sub = vici_create_section(name);
195                 add_subsection(name, sub, section);
196         }
197         return sub;
198 }
199
200 int vici_add_kv(VICISection* section, const char* key,
201                 const char* value, const char* subsection)
202 {
203         VICISection* target = section;
204         DBG("key: %s, value: %s, subsection: %s", key, value, subsection);
205
206         if (section == NULL || key == NULL) {
207                 connman_error("invalid parameter");
208                 return -1;
209         }
210
211         if (subsection)
212                 target = get_subsection(section, subsection);
213
214         add_kv_to_section(key, value, target);
215         return 0;
216 }
217
218 int vici_add_kvl(VICISection* section, const char* key,
219                 const char* value, const char* subsection)
220 {
221         VICISection* target = section;
222
223         DBG("key: %s, value: %s, subsection: %s", key, value, subsection);
224         if (section == NULL || key == NULL) {
225                 connman_error("invalid parameter");
226                 return -1;
227         }
228
229         if (subsection)
230                 target = get_subsection(section, subsection);
231
232         if (g_strcmp0(subsection, "children") == 0)
233                 target = get_subsection(target, "net");
234
235         add_kvl_to_section(key, value, target);
236         return 0;
237 }
238
239 static void add_list_to_section(char *key, GSList *list, VICISection *section)
240 {
241         if (section == NULL || key == NULL || list == NULL)
242                 return;
243
244         g_hash_table_insert(section->kvls, g_strdup(key), g_slist_copy_deep(list, (GCopyFunc)g_strdup, NULL));
245         return;
246 }
247
248 int vici_add_list(VICISection* section, char *key, GSList *list, const char* subsection)
249 {
250         VICISection* target = section;
251
252         DBG("key: %s, subsection: %s", key, subsection);
253         if (section == NULL || key == NULL) {
254                 connman_error("invalid parameter");
255                 return -1;
256         }
257
258         if (subsection)
259                 target = get_subsection(section, subsection);
260
261         if (g_strcmp0(subsection, "children") == 0)
262                 target = get_subsection(target, "net");
263
264         add_list_to_section(key, list, target);
265         return 0;
266 }
267
268 static char *load_cert_from_path(const char *path)
269 {
270         struct stat st;
271         FILE *fp = NULL;
272         int fd = 0;
273         size_t file_size = 0;
274         char *file_buff = NULL;
275
276         fp = fopen(path, "rb");
277         if (fp == NULL) {
278                 connman_error("fopen failed");
279                 return NULL;
280         }
281
282         fd = fileno(fp);
283         if (fd == -1) {
284                 connman_error("fp is not a valid stream");
285                 fclose(fp);
286                 return NULL;
287         }
288
289         fstat(fd, &st);
290         file_size = st.st_size;
291         file_buff = g_try_malloc0(sizeof(char)*st.st_size);
292         if (file_buff == NULL) {
293                 connman_error("g_try_malloc0 failed\n");
294                 fclose(fp);
295                 return NULL;
296         }
297
298         if (fread(file_buff, 1, file_size, fp) != file_size) {
299                 connman_error("file size not matched\n");
300                 g_free(file_buff);
301                 file_buff = NULL;
302         }
303
304         fclose(fp);
305         return file_buff;
306 }
307
308 int vici_add_cert_kv(VICISection *section, const char *key,
309                 const char *value, const char *subsection)
310 {
311         char *cert = NULL;
312         int ret = 0;
313
314         if (value == NULL) {
315                 DBG("value is null");
316                 return 0;
317         }
318
319         cert = load_cert_from_path(value);
320         if (!cert)
321                 return -1;
322
323         ret = vici_add_kv(section, key, (const char *)cert, subsection);
324         g_free(cert);
325         return ret;
326 }
327
328 int vici_add_cert_kvl(VICISection *section, const char *key,
329                 const char *value, const char *subsection)
330 {
331         char *cert = NULL;
332         int ret = 0;
333
334         cert = load_cert_from_path(value);
335         if (!cert)
336                 return -1;
337
338         ret = vici_add_kvl(section, key, (const char *)cert, subsection);
339         g_free(cert);
340         return ret;
341 }
342
343 static void *add_element(struct request *r, enum vici_element type,
344                                                  unsigned int size)
345 {
346         unsigned int newlen;
347         void *ret, *new;
348
349         if (r->used + size + 1 > r->allocated) {
350                 newlen = r->allocated;
351                 while (newlen < r->used + size + 1) {
352                         newlen *= 2;
353                 }
354                 new = realloc(r->sndbuf, newlen);
355                 if (!new) {
356                         r->err = -errno;
357                         return NULL;
358                 }
359                 r->sndbuf = new;
360                 r->allocated = newlen;
361         }
362         r->sndbuf[r->used++] = type;
363         ret = r->sndbuf + r->used;
364         r->used += size;
365         return ret;
366 }
367
368 static void section_start(struct request *r, const char *name)
369 {
370         uint8_t nlen;
371         char *pos;
372
373         nlen = strlen(name);
374         pos = add_element(r, VICI_SECTION_START, 1 + nlen);
375         if (pos) {
376                 pos[0] = nlen;
377                 memcpy(pos + 1, name, nlen);
378         }
379 }
380
381 static void section_end(struct request *r)
382 {
383         add_element(r, VICI_SECTION_END, 0);
384 }
385
386 static void key_value(struct request *r, const char *name,
387                            const void *buf, unsigned int buflen)
388 {
389         uint8_t nlen;
390         uint16_t vlen;
391         char *pos;
392
393         nlen = strlen(name);
394         pos = add_element(r, VICI_KEY_VALUE, 1 + nlen + sizeof(vlen) + buflen);
395         if (pos) {
396                 pos[0] = nlen;
397                 memcpy(pos + 1, name, nlen);
398                 vlen = htons(buflen);
399                 memcpy(pos + 1 + nlen, &vlen, sizeof(vlen));
400                 memcpy(pos + 1 + nlen + sizeof(vlen), buf, buflen);
401         }
402 }
403
404
405 static void list_start(struct request *r, const char *name)
406 {
407         uint8_t nlen;
408         char *pos;
409
410         nlen = strlen(name);
411         pos = add_element(r, VICI_LIST_START, 1 + nlen);
412         if (pos) {
413                 pos[0] = nlen;
414                 memcpy(pos + 1, name, nlen);
415         }
416 }
417
418 static void list_item(struct request *r, const void *buf,
419                                           unsigned int buflen)
420 {
421         uint16_t vlen;
422         char *pos;
423
424         pos = add_element(r, VICI_LIST_ITEM, sizeof(vlen) + buflen);
425         if (pos) {
426                 vlen = htons(buflen);
427                 memcpy(pos, &vlen, sizeof(vlen));
428                 memcpy(pos + sizeof(vlen), buf, buflen);
429         }
430 }
431
432 static void list_end(struct request *r)
433 {
434         add_element(r, VICI_LIST_END, 0);
435 }
436
437 static void destroy_vici_request(gpointer data)
438 {
439         struct request *req = (struct request *)data;
440         if(!req)
441                 return;
442
443         g_free(req->sndbuf);
444         g_free(req);
445 }
446
447 static int create_vici_request(enum vici_packet_type type, VICIClientCmd cmd,
448                                                   struct request **rp)
449 {
450         struct request *req = NULL;
451
452         if (cmd >= VICI_CMD_MAX || !rp)
453                 return -EINVAL;
454
455         req = g_try_new0(struct request, 1);
456         if (!req) {
457                 connman_error("g_try_new0 failed");
458                 return -ENOMEM;
459         }
460
461         req->used = 2;
462         req->used += strlen(vici_cmd_str[cmd]);
463         req->allocated = MIN(32, req->used);
464         req->sndbuf = g_try_new0(char, req->allocated);
465         if (!req->sndbuf) {
466                 connman_error("g_try_new0 failed");
467                 g_free(req);
468                 return -ENOMEM;
469         }
470
471         req->sndbuf[0] = type;
472         req->sndbuf[1] = req->used - 2; /* except for type and name length */
473         memcpy(req->sndbuf + 2, vici_cmd_str[cmd], req->used - 2);
474         req->hdr_len = req->used;
475         req->cmd = cmd;
476
477         *rp = req;
478
479         return 0;
480 }
481
482 static void write_section_kvs(VICISection *section, struct request *req)
483 {
484         GHashTableIter iter;
485         gpointer key, value;
486
487         if (section == NULL || req == NULL)
488                 return;
489
490         g_hash_table_iter_init (&iter, section->kvs);
491         while (g_hash_table_iter_next (&iter, &key, &value)) {
492                 if (!key || !value)
493                         continue;
494                 key_value(req, (const char*)key, (const void *)value, strlen((char *)value));
495         }
496
497         return;
498 }
499
500 static void write_list_item(gpointer data, gpointer user_data)
501 {
502         struct request *req = NULL;
503         char *value = NULL;
504
505         if (!data || !user_data)
506                 return;
507
508         value = (char *)data;
509         req = (struct request *)user_data;
510         list_item(req, value, strlen(value));
511
512         return;
513 }
514
515 static void write_section_kvls(VICISection *section, struct request *req)
516 {
517         GHashTableIter iter;
518         gpointer key, value;
519
520         if (section == NULL || req == NULL)
521                 return;
522
523         g_hash_table_iter_init (&iter, section->kvls);
524         while (g_hash_table_iter_next (&iter, &key, &value)) {
525                 if (!key || !value)
526                         continue;
527
528                 list_start(req, key);
529                 g_slist_foreach((GSList *)value, (GFunc)write_list_item, (gpointer)req);
530                 list_end(req);
531         }
532
533         return;
534 }
535
536 static void write_section(struct request *req, VICISection *section)
537 {
538         GHashTableIter iter;
539         gpointer key, value;
540
541         if (req == NULL || section == NULL)
542                 return;
543
544         if (section->name)
545                 section_start(req, section->name);
546
547         write_section_kvs(section, req);
548         write_section_kvls(section, req);
549
550         g_hash_table_iter_init(&iter, section->subsection);
551         while (g_hash_table_iter_next (&iter, &key, &value)) {
552                 if (!key || !value)
553                         continue;
554                 write_section(req, (VICISection *)value);
555         }
556
557         if (section->name)
558                 section_end(req);
559         return;
560 }
561
562 static int check_socket(int sock)
563 {
564         struct pollfd p_fd;
565         int res = 0;
566
567         p_fd.fd = sock;
568         p_fd.events = POLLIN | POLLOUT | POLLERR | POLLHUP | POLLNVAL;
569         res = poll((struct pollfd *) &p_fd, 1, 1);
570
571         if (res < 0) {
572                 connman_error("Polling error from socket\n");
573                 return -1;
574         } else if (res == 0) {
575                 connman_error( "poll timeout. socket is busy\n");
576                 return 1;
577         } else {
578
579                 if (p_fd.revents & POLLERR) {
580                         connman_error("Error! POLLERR from socket[%d]\n", sock);
581                         return -1;
582                 } else if (p_fd.revents & POLLHUP) {
583                         connman_error("Error! POLLHUP from socket[%d]\n", sock);
584                         return -1;
585                 } else if (p_fd.revents & POLLNVAL) {
586                         connman_error("Error! POLLNVAL from socket[%d]\n", sock);
587                         return -1;
588                 } else if (p_fd.revents & POLLIN) {
589                         return 0;
590                 } else if (p_fd.revents & POLLOUT) {
591                         return 0;
592                 }
593         }
594
595         connman_error("Unknown poll event [%d]\n", p_fd.revents);
596         return -1;
597 }
598
599 static int write_socket(int sock, char *data, int data_len)
600 {
601         int wbytes = 0;
602         int left_len = data_len;
603         char *ptr = data;
604         int res = 0;
605
606         if (sock < SOCK_FD_MIN || !data || data_len < 0)
607                 return -1;
608
609         res = check_socket(sock);
610         if (res < 0)
611                 return -1;
612         else if (res > 0)
613                 return -2;
614
615         errno = 0;
616         while (left_len) {
617                 wbytes = write(sock, ptr, left_len);
618                 if (wbytes <= 0) {
619                         connman_error("Failed to write data into socket[%d].\n", sock);
620                         break;
621                 }else if (wbytes < left_len) {
622                         left_len -= wbytes;
623                         ptr += wbytes;
624                 } else if (wbytes == left_len) {
625                         left_len = 0;
626                 } else {
627                         connman_error("Unknown error occurred.\n");
628                         break;
629                 }
630         }
631
632         if (left_len)
633                 return -1;
634         else
635                 return 0;
636 }
637
638 int send_vici_command(struct request *req, VICIClient *vici_client)
639 {
640         unsigned int size = 0;
641         int sock_fd = 0;
642         int res = 0;
643
644         if (req == NULL ||  vici_client == NULL) {
645                 connman_error("request is NULL\n");
646                 return -EINVAL;
647         }
648         sock_fd = vici_client->client_sock_fd;
649
650         size = htonl(req->used);
651         res = write_socket(sock_fd, (char *)&size, sizeof(size));
652         if (res != 0) {
653                 connman_error("failed to send size with network byte order\n");
654                 return -EIO;
655         }
656
657         res = write_socket(sock_fd, req->sndbuf, req->used);
658         if (res != 0) {
659                 connman_error("failed to send pkt\n");
660                 return -EIO;
661         }
662
663         if(req->cmd != VICI_CMD_REGISTER_CHILD_UPDOWN)
664                 vici_client->request_list = g_slist_append(vici_client->request_list, req);
665
666         return res;
667 }
668
669 static void print_vici_element(int elem_type, char *value, int sections)
670 {
671         int i = 0;
672
673
674         switch (elem_type) {
675         case VICI_SECTION_START:
676                 for (i = 0; i < sections - 1; i++)
677                         DBG("\t");
678                 DBG("%s = {\n", value);
679                 break;
680         case VICI_SECTION_END:
681                 for (i = 0; i < sections; i++)
682                         DBG("\t");
683                 DBG("}\n");
684                 break;
685         case VICI_KEY_VALUE:
686                 for (i = 0; i < sections; i++)
687                         DBG("\t");
688                 DBG("%s\n", value);
689                 break;
690         case VICI_LIST_START:
691                 for (i = 0; i < sections; i++)
692                         DBG("\t");
693                 DBG("%s = [", value);
694                 break;
695         case VICI_LIST_ITEM:
696                 DBG("%s, ", value);
697                 break;
698         case VICI_LIST_END:
699                 DBG("]\n");
700                 break;
701         default:
702                 break;
703         }
704         return;
705 }
706
707 static void debug_vici_message(char *buf, unsigned int size)
708 {
709         char temp[255];
710         unsigned int pos = 0;
711         int len = 0;
712         int sections = 0;
713         int type = -1;
714
715         if (buf == NULL || size == 0)
716                 return;
717
718         pos = 1;
719         while (pos < size) {
720
721                 type = buf[pos];
722                 pos++;
723                 switch (type) {
724                 case VICI_SECTION_START:
725                 {
726                         len = buf[pos];
727                         pos++;
728                         g_strlcpy(temp, (const gchar *)&buf[pos], len + 1);
729                         pos += len;
730                         sections++;
731                 }
732                         break;
733                 case VICI_SECTION_END:
734                 {
735                         sections--;
736                 }
737                         break;
738                 case VICI_KEY_VALUE:
739                 {
740                         int key_len = 0;
741                         int value_len = 0;
742
743                         key_len = buf[pos];
744                         pos++;
745                         g_strlcpy(temp, (const gchar *)&buf[pos], key_len + 1);
746                         temp[key_len] = '=';
747                         pos += (key_len + 1);
748                         value_len = buf[pos];
749                         pos++;
750                         g_strlcpy(temp + key_len + 1, (const gchar *)&buf[pos], value_len + 1);
751                         pos += value_len;
752                         len = key_len + 1 + value_len;
753                 }
754                         break;
755                 case VICI_LIST_START:
756                 {
757                         len = buf[pos];
758                         pos++;
759                         g_strlcpy(temp, (const gchar *)&buf[pos], len + 1);
760                         pos += len;
761                 }
762                         break;
763                 case VICI_LIST_ITEM:
764                 {
765                         pos++;
766                         len = buf[pos];
767                         pos++;
768                         g_strlcpy(temp, (const gchar *)&buf[pos], len + 1);
769                         pos += len;
770                 }
771                         break;
772                 case VICI_LIST_END:
773                         break;
774                 default:
775                         break;
776                 }
777                 print_vici_element(type, temp, sections);
778         }
779         return;
780 }
781
782 static unsigned int extract_key_value(char *buf, unsigned int pos, char **key, char **value)
783 {
784         int key_len = 0;
785         int value_len = 0;
786
787         key_len = buf[pos];
788         pos++;
789         *key = g_strndup((const gchar *)&buf[pos], key_len);
790         pos+=(key_len + 1);
791         value_len = buf[pos];
792         pos++;
793         *value = g_strndup((const gchar *)&buf[pos], value_len);
794         pos+=value_len;
795         return pos;
796 }
797
798 static gboolean extract_request_result(char *buf, unsigned int size, char **err)
799 {
800         gboolean success = FALSE;
801         unsigned int pos = 0;
802         int type = -1;
803
804         pos = 1;
805         while (pos < size) {
806
807                 type = buf[pos];//3
808                 pos++;
809                 if (type == VICI_KEY_VALUE) {
810                         char *key = NULL;
811                         char *value = NULL;
812                         pos = extract_key_value(buf, pos, &key, &value);
813                         DBG("pos : %d size : %d\n", pos, size);
814
815                         /* TODO :remove this after debug */
816                         DBG("key : %s value : %s\n", key, value);
817                         if (g_strcmp0(key, "success") == 0)
818                                 (g_strcmp0(value, "yes") == 0)?(success = TRUE):(success = FALSE);
819
820                         if (g_strcmp0(key, "errmsg"))
821                                 *err = g_strdup(value);
822                         g_free(key);
823                         g_free(value);
824                 }
825         }
826         return success;
827 }
828
829 static int handle_vici_result(gboolean success, int cmd, char * err)
830 {
831         int ret = 0;
832         if (success)
833                 return 0;
834
835         g_free(err);
836
837         switch (cmd) {
838         case    VICI_CMD_LOAD_CONN:
839                 ret = EINVAL;
840                 break;
841         case    VICI_CMD_LOAD_SHARED:
842                 ret = EINVAL;
843                 break;
844         case    VICI_CMD_LOAD_CERT:
845                 ret = EINVAL;
846                 break;
847         case    VICI_CMD_LOAD_AUTH:
848                 ret = 0;
849                 break;
850         case    VICI_CMD_LOAD_KEY:
851                 ret = EINVAL;
852                 break;
853         case    VICI_CMD_INITIATE:
854                 ret = ECONNABORTED;
855                 break;
856         case    VICI_CMD_TERMINATE:
857                 ret = EINVAL;
858                 break;
859         default:
860                 break;
861         }
862
863         DBG(" %s failed with %d!\n", vici_cmd_str[cmd], ret);
864         return ret;
865 }
866
867 static int process_vici_response(struct request * req)
868 {
869         char *err = NULL;
870         gboolean success = FALSE;
871         int ret = 0;
872
873         if (!req)
874                 return -1;
875
876         if (!req->rcvbuf || req->rcvbuf[0] != VICI_CMD_RESPONSE)
877                 return -1;
878
879         //TODO: remove below when there's no further problem.
880         debug_vici_message(req->rcvbuf, req->rcv_pkt_size);
881
882         success = extract_request_result(req->rcvbuf, req->rcv_pkt_size, &err);
883         ret = handle_vici_result(success, req->cmd, err);
884
885         return ret;
886 }
887
888 int vici_send_request(VICIClient *vici_client, VICIClientCmd cmd, VICISection *root)
889 {
890         struct request *req = NULL;
891         int ret;
892
893         DBG("%s", vici_cmd_str[cmd]);
894         ret = create_vici_request(VICI_CMD_REQUEST, cmd, &req);
895         if (ret < 0) {
896                 connman_error("error on create_request\n");
897                 return ret;
898         }
899
900         write_section(req, root);
901         //TODO: remove below when there's no further problem.
902         debug_vici_message(req->sndbuf + req->hdr_len - 1, req->used - req->hdr_len + 1);
903
904         ret = send_vici_command(req, vici_client);
905         if (ret < 0) {
906                 destroy_vici_request(req);
907                 connman_error("error on send_command\n");
908         }
909
910         return ret;
911 }
912
913
914 int vici_set_event_cb(VICIClient *vici_client, vici_event_cb cb, gpointer user_data)
915 {
916         struct request *req = NULL;
917         int ret;
918
919         DBG("%s",vici_cmd_str[VICI_EVENT_CHILD_UP]);
920         ret = create_vici_request(VICI_EVENT_REGISTER, VICI_CMD_REGISTER_CHILD_UPDOWN, &req);
921         if (ret < 0) {
922                 connman_error("error on create_request\n");
923                 return ret;
924         }
925
926         ret = send_vici_command(req, vici_client);
927         if (ret < 0) {
928                 connman_error("error on send_command\n");
929         }
930
931         destroy_vici_request(req);
932         vici_client->event_cb = cb;
933         vici_client->event_user_data = user_data;
934
935         return ret;
936
937 }
938
939 static int get_socket_from_source(GIOChannel *source, GIOCondition condition)
940 {
941         int sock = -1;
942         /* check socket */
943         sock = g_io_channel_unix_get_fd(source);
944         if (sock < SOCK_FD_MIN)
945                 return -1;
946
947         if ((condition & G_IO_ERR) || (condition & G_IO_HUP) || (condition & G_IO_NVAL)) {
948                 connman_error("G_IO_ERR/G_IO_HUP/G_IO_NVAL received sock [%d] condition [%d]\n", sock, condition);
949                 //TODO: handle the breaking socket
950                 return -1;
951         }
952         return sock;
953 }
954
955 static int read_socket(int sock, char *data, unsigned int data_len)
956 {
957         int rbytes = 0;
958         int total_rbytes = 0;
959
960         if (sock < SOCK_FD_MIN || !data || data_len <= 0)
961                 return -1;
962
963         while (data_len > 0) {
964                 errno = 0;
965                 rbytes = read(sock, data, data_len);
966                 if (rbytes <= 0)
967                         return -1;
968
969                 total_rbytes += rbytes;
970                 data += rbytes;
971                 data_len -= rbytes;
972         }
973
974         return total_rbytes;
975 }
976
977 static int recv_vici_pkt(int sock, struct _VICIClient *vici_client)
978 {
979         if(!vici_client)
980                 return -1;
981
982         if (vici_client->rcv_pkt_size == 0) {
983                 unsigned int pkt_size = 0;
984                 if (read_socket(sock, (char *)&pkt_size, sizeof(pkt_size)) < 0)
985                         return -1;
986
987                 vici_client->rcv_pkt_size = ntohl(pkt_size);
988                 /* TODO :REMOVE THIS AFTER DEBUG */
989                 DBG("rcv_pkt_size [%d] will be recved\n", vici_client->rcv_pkt_size);
990         } else {
991
992                 DBG("rcv_pkt_size [%d] is recved\n", vici_client->rcv_pkt_size);
993                 char *buf = NULL;
994                 buf = g_try_malloc0(vici_client->rcv_pkt_size);
995                 if (buf == NULL)
996                         return -1;
997
998                 if (read_socket(sock, buf, vici_client->rcv_pkt_size) < 0) {
999                         g_free(buf);
1000                         return -1;
1001                 }
1002                 vici_client->rcvbuf = buf;
1003         }
1004
1005         return 0;
1006 }
1007
1008 static struct request *pop_vici_request(VICIClient *vici_client)
1009 {
1010         GSList *list = NULL;
1011
1012         if (!vici_client)
1013                 return NULL;
1014
1015         list = vici_client->request_list;
1016         if(!list)
1017                 return NULL;
1018
1019         return list->data;
1020 }
1021
1022 static void process_vici_reply(VICIClient *vici_client)
1023 {
1024         struct request *req;
1025         int ret = 0;
1026
1027         if (!vici_client)
1028                 return;
1029
1030         /* get first request */
1031         req = pop_vici_request(vici_client);
1032         if (!req)
1033                 return;
1034
1035         req->rcvbuf = vici_client->rcvbuf;
1036         req->rcv_pkt_size = vici_client->rcv_pkt_size;
1037
1038         ret = process_vici_response(req);
1039         vici_client->request_list = g_slist_remove(vici_client->request_list, req);
1040         destroy_vici_request(req);
1041
1042         /* TODO :remove this after debug */
1043         DBG("left request reply : %d", g_slist_length(vici_client->request_list));
1044
1045         if (ret != 0 || g_slist_length(vici_client->request_list) == 0)
1046                 vici_client->reply_cb(ret, vici_client->reply_user_data);
1047
1048 }
1049
1050 static int extract_event_name(char *buf, unsigned int size, char *temp)
1051 {
1052         int pos = 1;
1053         int name_len = 0;
1054         name_len = buf[pos];
1055         pos++;
1056         DBG("event len: %d", name_len);
1057         while(pos <  size && pos - 2 < name_len) {
1058                 temp[pos - 2] = buf[pos];
1059                 pos++;
1060         }
1061         temp[pos] = '\0';
1062         DBG("event name: %s", temp);
1063         return pos;
1064 }
1065
1066 static char *vici_get_value(char *buf, unsigned int pos, unsigned int size, char *search_key)
1067 {
1068         int type = -1;
1069
1070         pos = 1;
1071         while (pos < size) {
1072
1073                 type = buf[pos];//3
1074                 pos++;
1075                 if (type == VICI_KEY_VALUE) {
1076                         char *key = NULL;
1077                         char *value = NULL;
1078                         pos = extract_key_value(buf, pos, &key, &value);
1079                         if (g_strcmp0(search_key, key) == 0) {
1080                                 g_free(key);
1081                                 return value;
1082                         }
1083
1084                         g_free(key);
1085                         g_free(value);
1086                 }
1087         }
1088         return NULL;
1089 }
1090
1091 static void process_child_updown(VICIClient *vici_client,char *buf, unsigned int size)
1092 {
1093         char *state = NULL;
1094
1095         state = vici_get_value(buf, 0, size, "state");
1096         if (g_strcmp0(state, "ESTABLISHED") == 0) {
1097                 DBG("ESTABLISHED");
1098                 vici_client->event_cb(VICI_EVENT_CHILD_UP, vici_client->event_user_data);
1099         } else if (g_strcmp0(state, "DELETING") == 0) {
1100                 DBG("DELETING");
1101                 vici_client->event_cb(VICI_EVENT_CHILD_DOWN, vici_client->event_user_data);
1102         } else {
1103                 DBG("Unknown event");
1104         }
1105         g_free(state);
1106         return;
1107 }
1108
1109 static void process_vici_event(VICIClient *vici_client)
1110 {
1111         char *buf = NULL;
1112         unsigned int size = 0;
1113         unsigned int pos = 0;
1114         char temp[256] = {0,};
1115         if (!vici_client || !(vici_client->rcvbuf) || vici_client->rcv_pkt_size == 0)
1116                 return;
1117
1118         buf = vici_client->rcvbuf;
1119         size = vici_client->rcv_pkt_size;
1120
1121         pos = extract_event_name(buf, size, temp);
1122         /* TODO: remove below after debug */
1123         /* add parser */
1124         if (g_strcmp0(temp, "child-updown") == 0)
1125                 process_child_updown(vici_client, buf + pos -1, size - pos);
1126 }
1127
1128 static void process_vici_packet(VICIClient *vici_client, char *buf)
1129 {
1130
1131         if (!vici_client || !buf)
1132                 return;
1133
1134         if (buf[0] == VICI_CMD_RESPONSE) {
1135                 DBG("VICI_CMD_RESPONSE\n");
1136                 process_vici_reply(vici_client);
1137         } else if (buf[0] == VICI_EVENT_CONFIRM) {
1138                 DBG("VICI_EVENT_CONFIRM\n");
1139         } else if (buf[0] == VICI_EVENT) {
1140                 DBG("VICI_EVENT");
1141                 process_vici_event(vici_client);
1142         } else {
1143                 DBG("Not handled [%u]", buf[0]);
1144         }
1145         return;
1146 }
1147
1148 static gboolean process_vici_msg(GIOChannel *source,
1149                                            GIOCondition condition,
1150                                            gpointer user_data)
1151 {
1152         VICIClient *vici_client = NULL;
1153         int sock = 0;
1154
1155         vici_client = (VICIClient *)user_data;
1156         if (!vici_client)
1157                 return FALSE;
1158
1159         sock = get_socket_from_source(source, condition);
1160         if (sock < 0)
1161                 return FALSE;
1162
1163
1164         if(recv_vici_pkt(sock, vici_client) < 0)
1165                 return FALSE;
1166
1167         if (!vici_client->rcvbuf) {
1168                 return TRUE;
1169         }
1170
1171         process_vici_packet(vici_client, vici_client->rcvbuf);
1172         g_free(vici_client->rcvbuf);
1173         vici_client->rcvbuf = NULL;
1174         vici_client->rcv_pkt_size = 0;
1175
1176         return TRUE;
1177 }
1178
1179 static int str_to_socket_addr(const char *uri, struct sockaddr_un *addr)
1180 {
1181         memset(addr, 0, sizeof(*addr));
1182         addr->sun_family = AF_UNIX;
1183         strncpy(addr->sun_path, uri, sizeof(addr->sun_path));
1184
1185         addr->sun_path[sizeof(addr->sun_path)-1] = '\0';
1186
1187         return offsetof(struct sockaddr_un, sun_path) + strlen(addr->sun_path);
1188 }
1189
1190 static int connect_socket(const char *uri)
1191 {
1192         struct sockaddr_un addr;
1193         int len, fd;
1194
1195         fd = socket(AF_UNIX, SOCK_STREAM, 0);
1196         if (fd < 0) {
1197                 connman_error("socket() failed");
1198                 return -errno;
1199         }
1200
1201         len = str_to_socket_addr(uri, &addr);
1202         if (len == -1) {
1203                 connman_error("str_to_socket_addr failed");
1204                 close(fd);
1205                 return -1;
1206         }
1207
1208         if (connect(fd, (struct sockaddr*)&addr, len) < 0) {
1209                 connman_error("connect failed. errno %d/%s", errno, strerror(errno));
1210                 close(fd);
1211                 return -errno;
1212         }
1213
1214         return fd;
1215 }
1216
1217 static int initialize_vici_source(VICIClient *vici_client)
1218 {
1219         GIOChannel *vici_channel;
1220         if (!vici_client) {
1221                 return -ENOMEM;
1222         }
1223
1224         vici_client->client_sock_fd = connect_socket(VICI_DEFAULT_URI);
1225         if (vici_client->client_sock_fd < 0) {
1226                 connman_error("connect_socket failed");
1227                 return -EIO;
1228         }
1229
1230         vici_channel = g_io_channel_unix_new(vici_client->client_sock_fd);
1231         if (!vici_channel) {
1232                 connman_error("g_io_channel_unix_new failed");
1233                 close(vici_client->client_sock_fd);
1234                 return -ENOMEM;
1235         }
1236
1237         vici_client->client_watch = g_io_add_watch_full(vici_channel,
1238                                                  G_PRIORITY_LOW,
1239                                                  G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
1240                                                  (GIOFunc)process_vici_msg,
1241                                                  (gpointer)vici_client,
1242                                                  NULL);
1243         g_io_channel_unref(vici_channel);
1244         return 0;
1245 }
1246
1247 int vici_initialize(VICIClient **vici_client)
1248 {
1249         int ret = 0;
1250
1251         *vici_client = g_try_new0(VICIClient, 1);
1252         if (!*vici_client) {
1253                 connman_error("out of memory");
1254                 return -ENOMEM;
1255         }
1256
1257         ret = initialize_vici_source(*vici_client);
1258         if (ret != 0) {
1259                 g_free(*vici_client);
1260                 return ret;
1261         }
1262
1263         DBG("connected");
1264         return 0;
1265 }
1266
1267 void vici_set_request_reply_cb(VICIClient *vici_client, vici_request_reply_cb reply_cb, gpointer user_data)
1268 {
1269         vici_client->reply_cb = reply_cb;
1270         vici_client->reply_user_data = user_data;
1271 }
1272
1273 int vici_deinitialize(VICIClient *vici_client)
1274 {
1275         if (vici_client->client_watch > 0) {
1276                 g_source_remove(vici_client->client_watch);
1277                 vici_client->client_watch = 0;
1278         }
1279
1280         close(vici_client->client_sock_fd);
1281         g_slist_free_full(vici_client->request_list, destroy_vici_request);
1282         g_free(vici_client->rcvbuf);
1283         g_free(vici_client);
1284
1285         return 0;
1286 }