Fix issues reported by a static analyzer
[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         NULL,
72 };
73
74 struct request {
75         unsigned int allocated;
76         unsigned int used;
77         unsigned int hdr_len;
78         char *sndbuf;
79         int cmd;
80         int err;
81         /* process reply */
82         unsigned int rcv_pkt_size;
83         char *rcvbuf;
84         /* davici_cb cb; */
85         void *user;
86 };
87
88 struct _VICIClient {
89         /* io data */
90         int client_sock_fd;
91         int client_watch;
92         GSList *request_list;
93         vici_connect_reply_cb reply;
94         void *ipsec_user_data;
95 };
96
97 struct _VICISection {
98         char *name;
99         GHashTable *kvs;
100         GHashTable *kvls;
101         GHashTable *subsection;
102 };
103
104 static void remove_list(gpointer data)
105 {
106         if (data == NULL)
107                 return;
108
109         g_slist_free_full((GSList *)data, g_free);
110 }
111
112 void vici_destroy_section(VICISection* section)
113 {
114         g_free(section->name);
115         g_hash_table_destroy(section->kvs);
116         g_hash_table_destroy(section->kvls);
117         g_hash_table_destroy(section->subsection);
118         g_free(section);
119 }
120
121 static void free_section(gpointer data)
122 {
123         VICISection* section = (VICISection*)data;
124         vici_destroy_section(section);
125 }
126
127 VICISection* vici_create_section(const char* name)
128 {
129         VICISection* section;
130
131         section = g_try_new0(VICISection, 1);
132         if (!section) {
133                 connman_error("Failed to create section");
134                 return NULL;
135         }
136
137         if (name)
138                 section->name = g_strdup(name);
139         section->kvs = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
140         section->kvls = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, remove_list);
141         section->subsection = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, free_section);
142         return section;
143 }
144
145 int add_subsection(const char* name, VICISection* child, VICISection* section)
146 {
147         if (section == NULL || name == NULL || child == NULL) {
148                 connman_error("invalid parameter");
149                 return -1;
150         }
151
152         g_hash_table_insert(section->subsection, g_strdup(name), child);
153         return 0;
154 }
155
156 static int add_kvl_to_section(const char* key, const char* value, VICISection* section)
157 {
158         GSList *list = NULL;
159         if (section == NULL || key == NULL || value == NULL) {
160                 connman_error("invalid parameter");
161                 return -1;
162         }
163
164         list = g_hash_table_lookup(section->kvls, key);
165         if (list == NULL)
166                 list = g_slist_alloc();
167
168         list = g_slist_prepend(list, g_strdup(value));
169         g_hash_table_replace(section->kvls, g_strdup(key), list);
170         return 0;
171 }
172
173 static int add_kv_to_section(const char* key, const char* value, VICISection* section)
174 {
175         if (section == NULL || key == NULL || value == NULL) {
176                 connman_error("invalid parameter");
177                 return -1;
178         }
179
180         g_hash_table_insert(section->kvs, g_strdup(key), g_strdup(value));
181         return 0;
182 }
183
184 static VICISection* get_subsection(VICISection* section, const char* name)
185 {
186         VICISection* sub = g_hash_table_lookup(section->subsection, name);
187         if (sub == NULL) {
188                 sub = vici_create_section(name);
189                 add_subsection(name, sub, section);
190         }
191         return sub;
192 }
193
194 int vici_add_kv(VICISection* section, const char* key,
195                 const char* value, const char* subsection)
196 {
197         VICISection* target = section;
198         DBG("key: %s, value: %s, subsection: %s", key, value, subsection);
199
200         if (section == NULL || key == NULL) {
201                 connman_error("invalid parameter");
202                 return -1;
203         }
204
205         if (subsection)
206                 target = get_subsection(section, subsection);
207
208         add_kv_to_section(key, value, target);
209         return 0;
210 }
211
212 int vici_add_kvl(VICISection* section, const char* key,
213                 const char* value, const char* subsection)
214 {
215         VICISection* target = section;
216
217         DBG("key: %s, value: %s, subsection: %s", key, value, subsection);
218         if (section == NULL || key == NULL) {
219                 connman_error("invalid parameter");
220                 return -1;
221         }
222
223         if (subsection)
224                 target = get_subsection(section, subsection);
225
226         if (g_strcmp0(subsection, "children") == 0)
227                 target = get_subsection(target, "net");
228
229         add_kvl_to_section(key, value, target);
230         return 0;
231 }
232
233 static void add_list_to_section(char *key, GSList *list, VICISection *section)
234 {
235         if (section == NULL || key == NULL || list == NULL)
236                 return;
237
238         g_hash_table_insert(section->kvls, g_strdup(key), g_slist_copy(list));
239         return;
240 }
241
242 int vici_add_list(VICISection* section, char *key, GSList *list, const char* subsection)
243 {
244         VICISection* target = section;
245
246         DBG("key: %s, subsection: %s", key, subsection);
247         if (section == NULL || key == NULL) {
248                 connman_error("invalid parameter");
249                 return -1;
250         }
251
252         if (subsection)
253                 target = get_subsection(section, subsection);
254
255         if (g_strcmp0(subsection, "children") == 0)
256                 target = get_subsection(target, "net");
257
258         add_list_to_section(key, list, target);
259         return 0;
260 }
261
262 static char *load_cert_from_path(const char *path)
263 {
264         struct stat st;
265         FILE *fp = NULL;
266         int fd = 0;
267         size_t file_size = 0;
268         char *file_buff = NULL;
269
270         fp = fopen(path, "rb");
271         fd = fileno(fp);
272         fstat(fd, &st);
273         file_size = st.st_size;
274         file_buff = g_try_malloc0(sizeof(char)*st.st_size);
275         if (file_buff == NULL) {
276                 connman_error("g_try_malloc0 failed\n");
277                 fclose(fp);
278                 return NULL;
279         }
280
281         if (fread(file_buff, 1, file_size, fp) != file_size) {
282                 connman_error("file size not matched\n");
283                 g_free(file_buff);
284                 file_buff = NULL;
285         }
286
287         fclose(fp);
288         return file_buff;
289 }
290
291 int vici_add_cert_kv(VICISection *section, const char *key,
292                 const char *value, const char *subsection)
293 {
294         char *cert = NULL;
295         int ret = 0;
296
297         if (value == NULL) {
298                 DBG("value is null");
299                 return 0;
300         }
301
302         cert = load_cert_from_path(value);
303         if (!cert)
304                 return -1;
305
306         ret = vici_add_kv(section, key, (const char *)cert, subsection);
307         g_free(cert);
308         return ret;
309 }
310
311 int vici_add_cert_kvl(VICISection *section, const char *key,
312                 const char *value, const char *subsection)
313 {
314         char *cert = NULL;
315         int ret = 0;
316
317         cert = load_cert_from_path(value);
318         if (!cert)
319                 return -1;
320
321         ret = vici_add_kvl(section, key, (const char *)cert, subsection);
322         g_free(cert);
323         return ret;
324 }
325
326 static void *add_element(struct request *r, enum vici_element type,
327                                                  unsigned int size)
328 {
329         unsigned int newlen;
330         void *ret, *new;
331
332         if (r->used + size + 1 > r->allocated) {
333                 newlen = r->allocated;
334                 while (newlen < r->used + size + 1) {
335                         newlen *= 2;
336                 }
337                 new = realloc(r->sndbuf, newlen);
338                 if (!new) {
339                         r->err = -errno;
340                         return NULL;
341                 }
342                 r->sndbuf = new;
343                 r->allocated = newlen;
344         }
345         r->sndbuf[r->used++] = type;
346         ret = r->sndbuf + r->used;
347         r->used += size;
348         return ret;
349 }
350
351 static void section_start(struct request *r, const char *name)
352 {
353         uint8_t nlen;
354         char *pos;
355
356         nlen = strlen(name);
357         pos = add_element(r, VICI_SECTION_START, 1 + nlen);
358         if (pos) {
359                 pos[0] = nlen;
360                 memcpy(pos + 1, name, nlen);
361         }
362 }
363
364 static void section_end(struct request *r)
365 {
366         add_element(r, VICI_SECTION_END, 0);
367 }
368
369 static void key_value(struct request *r, const char *name,
370                            const void *buf, unsigned int buflen)
371 {
372         uint8_t nlen;
373         uint16_t vlen;
374         char *pos;
375
376         nlen = strlen(name);
377         pos = add_element(r, VICI_KEY_VALUE, 1 + nlen + sizeof(vlen) + buflen);
378         if (pos) {
379                 pos[0] = nlen;
380                 memcpy(pos + 1, name, nlen);
381                 vlen = htons(buflen);
382                 memcpy(pos + 1 + nlen, &vlen, sizeof(vlen));
383                 memcpy(pos + 1 + nlen + sizeof(vlen), buf, buflen);
384         }
385 }
386
387
388 static void list_start(struct request *r, const char *name)
389 {
390         uint8_t nlen;
391         char *pos;
392
393         nlen = strlen(name);
394         pos = add_element(r, VICI_LIST_START, 1 + nlen);
395         if (pos) {
396                 pos[0] = nlen;
397                 memcpy(pos + 1, name, nlen);
398         }
399 }
400
401 static void list_item(struct request *r, const void *buf,
402                                           unsigned int buflen)
403 {
404         uint16_t vlen;
405         char *pos;
406
407         pos = add_element(r, VICI_LIST_ITEM, sizeof(vlen) + buflen);
408         if (pos) {
409                 vlen = htons(buflen);
410                 memcpy(pos, &vlen, sizeof(vlen));
411                 memcpy(pos + sizeof(vlen), buf, buflen);
412         }
413 }
414
415 static void list_end(struct request *r)
416 {
417         add_element(r, VICI_LIST_END, 0);
418 }
419
420 static void destroy_vici_request(gpointer data)
421 {
422         struct request *req = (struct request *)data;
423         if(!req)
424                 return;
425
426         g_free(req->sndbuf);
427         g_free(req->rcvbuf);
428         g_free(req);
429 }
430
431 static int create_vici_request(enum vici_packet_type type, VICIClientCmd cmd,
432                                                   struct request **rp)
433 {
434         struct request *req = NULL;
435
436         if (cmd >= VICI_CMD_MAX || !rp)
437                 return -EINVAL;
438
439         req = g_try_new0(struct request, 1);
440         if (!req) {
441                 connman_error("g_try_new0 failed");
442                 return -ENOMEM;
443         }
444
445         req->used = 2;
446         req->used += strlen(vici_cmd_str[cmd]);
447         req->allocated = MIN(32, req->used);
448         req->sndbuf = g_try_new0(char, req->allocated);
449         if (!req->sndbuf) {
450                 connman_error("g_try_new0 failed");
451                 g_free(req);
452                 return -ENOMEM;
453         }
454
455         req->sndbuf[0] = type;
456         req->sndbuf[1] = req->used - 2; /* except for type and name length */
457         memcpy(req->sndbuf + 2, vici_cmd_str[cmd], req->used - 2);
458         req->hdr_len = req->used;
459         req->cmd = cmd;
460
461         *rp = req;
462
463         return 0;
464 }
465
466 static void write_section_kvs(VICISection *section, struct request *req)
467 {
468         GHashTableIter iter;
469         gpointer key, value;
470
471         if (section == NULL || req == NULL)
472                 return;
473
474         g_hash_table_iter_init (&iter, section->kvs);
475         while (g_hash_table_iter_next (&iter, &key, &value)) {
476                 if (!key || !value)
477                         continue;
478                 key_value(req, (const char*)key, (const void *)value, strlen((char *)value));
479         }
480
481         return;
482 }
483
484 static void write_list_item(gpointer data, gpointer user_data)
485 {
486         struct request *req = NULL;
487         char *value = NULL;
488
489         if (!data || !user_data)
490                 return;
491
492         value = (char *)data;
493         req = (struct request *)user_data;
494         list_item(req, value, strlen(value));
495
496         return;
497 }
498
499 static void write_section_kvls(VICISection *section, struct request *req)
500 {
501         GHashTableIter iter;
502         gpointer key, value;
503
504         if (section == NULL || req == NULL)
505                 return;
506
507         g_hash_table_iter_init (&iter, section->kvls);
508         while (g_hash_table_iter_next (&iter, &key, &value)) {
509                 if (!key || !value)
510                         continue;
511
512                 list_start(req, key);
513                 g_slist_foreach((GSList *)value, (GFunc)write_list_item, (gpointer)req);
514                 list_end(req);
515         }
516
517         return;
518 }
519
520 static void write_section(struct request *req, VICISection *section)
521 {
522         GHashTableIter iter;
523         gpointer key, value;
524
525         if (req == NULL || section == NULL)
526                 return;
527
528         if (section->name)
529                 section_start(req, section->name);
530
531         write_section_kvs(section, req);
532         write_section_kvls(section, req);
533
534         g_hash_table_iter_init(&iter, section->subsection);
535         while (g_hash_table_iter_next (&iter, &key, &value)) {
536                 if (!key || !value)
537                         continue;
538                 write_section(req, (VICISection *)value);
539         }
540
541         if (section->name)
542                 section_end(req);
543         return;
544 }
545
546 static int check_socket(int sock)
547 {
548         struct pollfd p_fd;
549         int res = 0;
550
551         p_fd.fd = sock;
552         p_fd.events = POLLIN | POLLOUT | POLLERR | POLLHUP | POLLNVAL;
553         res = poll((struct pollfd *) &p_fd, 1, 1);
554
555         if (res < 0) {
556                 connman_error("Polling error from socket\n");
557                 return -1;
558         } else if (res == 0) {
559                 connman_error( "poll timeout. socket is busy\n");
560                 return 1;
561         } else {
562
563                 if (p_fd.revents & POLLERR) {
564                         connman_error("Error! POLLERR from socket[%d]\n", sock);
565                         return -1;
566                 } else if (p_fd.revents & POLLHUP) {
567                         connman_error("Error! POLLHUP from socket[%d]\n", sock);
568                         return -1;
569                 } else if (p_fd.revents & POLLNVAL) {
570                         connman_error("Error! POLLNVAL from socket[%d]\n", sock);
571                         return -1;
572                 } else if (p_fd.revents & POLLIN) {
573                         return 0;
574                 } else if (p_fd.revents & POLLOUT) {
575                         return 0;
576                 }
577         }
578
579         connman_error("Unknown poll event [%d]\n", p_fd.revents);
580         return -1;
581 }
582
583 static int write_socket(int sock, char *data, int data_len)
584 {
585         int wbytes = 0;
586         int left_len = data_len;
587         char *ptr = data;
588         int res = 0;
589
590         if (sock < SOCK_FD_MIN || !data || data_len < 0)
591                 return -1;
592
593         res = check_socket(sock);
594         if (res < 0)
595                 return -1;
596         else if (res > 0)
597                 return -2;
598
599         errno = 0;
600         while (left_len) {
601                 wbytes = write(sock, ptr, left_len);
602                 if (wbytes <= 0) {
603                         connman_error("Failed to write data into socket[%d].\n", sock);
604                         break;
605                 }else if (wbytes < left_len) {
606                         left_len -= wbytes;
607                         ptr += wbytes;
608                 } else if (wbytes == left_len) {
609                         left_len = 0;
610                 } else {
611                         connman_error("Unknown error occurred.\n");
612                         break;
613                 }
614         }
615
616         if (left_len)
617                 return -1;
618         else
619                 return 0;
620 }
621
622 int send_vici_command(struct request *req, VICIClient *vici_client)
623 {
624         unsigned int size = 0;
625         int res = 0;
626
627         if (req == NULL) {
628                 connman_error("request is NULL\n");
629                 return -EINVAL;
630         }
631
632         size = htonl(req->used);
633         res = write_socket(vici_client->client_sock_fd, (char *)&size, sizeof(size));
634         if (res != 0) {
635                 connman_error("failed to send size with network byte order\n");
636                 return -EIO;
637         }
638
639         res = write_socket(vici_client->client_sock_fd, req->sndbuf, req->used);
640         if (res != 0) {
641                 connman_error("failed to send pkt\n");
642                 return -EIO;
643         }
644
645         vici_client->request_list = g_slist_append(vici_client->request_list, req);
646         return res;
647 }
648
649 static void print_vici_element(int elem_type, char *value, int sections)
650 {
651         int i = 0;
652
653
654         switch (elem_type) {
655         case VICI_SECTION_START:
656                 for (i = 0; i < sections - 1; i++)
657                         DBG("\t");
658                 DBG("%s = {\n", value);
659                 break;
660         case VICI_SECTION_END:
661                 for (i = 0; i < sections; i++)
662                         DBG("\t");
663                 DBG("}\n");
664                 break;
665         case VICI_KEY_VALUE:
666                 for (i = 0; i < sections; i++)
667                         DBG("\t");
668                 DBG("%s\n", value);
669                 break;
670         case VICI_LIST_START:
671                 for (i = 0; i < sections; i++)
672                         DBG("\t");
673                 DBG("%s = [", value);
674                 break;
675         case VICI_LIST_ITEM:
676                 DBG("%s, ", value);
677                 break;
678         case VICI_LIST_END:
679                 DBG("]\n");
680                 break;
681         default:
682                 break;
683         }
684         return;
685 }
686
687 static void debug_vici_message(char *buf, unsigned int size)
688 {
689         char temp[255];
690         unsigned int pos = 0;
691         int len = 0;
692         int sections = 0;
693         int type = -1;
694
695         if (buf == NULL || size == 0)
696                 return;
697
698         pos = 1;
699         while (pos < size) {
700
701                 type = buf[pos];
702                 pos++;
703                 switch (type) {
704                 case VICI_SECTION_START:
705                 {
706                         len = buf[pos];
707                         pos++;
708                         g_strlcpy(temp, (const gchar *)&buf[pos], len + 1);
709                         pos += len;
710                         sections++;
711                 }
712                         break;
713                 case VICI_SECTION_END:
714                 {
715                         sections--;
716                 }
717                         break;
718                 case VICI_KEY_VALUE:
719                 {
720                         int key_len = 0;
721                         int value_len = 0;
722
723                         key_len = buf[pos];
724                         pos++;
725                         g_strlcpy(temp, (const gchar *)&buf[pos], key_len + 1);
726                         temp[key_len] = '=';
727                         pos += (key_len + 1);
728                         value_len = buf[pos];
729                         pos++;
730                         g_strlcpy(temp + key_len + 1, (const gchar *)&buf[pos], value_len + 1);
731                         pos += value_len;
732                         len = key_len + 1 + value_len;
733                 }
734                         break;
735                 case VICI_LIST_START:
736                 {
737                         len = buf[pos];
738                         pos++;
739                         g_strlcpy(temp, (const gchar *)&buf[pos], len + 1);
740                         pos += len;
741                 }
742                         break;
743                 case VICI_LIST_ITEM:
744                 {
745                         pos++;
746                         len = buf[pos];
747                         pos++;
748                         g_strlcpy(temp, (const gchar *)&buf[pos], len + 1);
749                         pos += len;
750                 }
751                         break;
752                 case VICI_LIST_END:
753                         break;
754                 default:
755                         break;
756                 }
757                 print_vici_element(type, temp, sections);
758         }
759         return;
760 }
761
762 static unsigned int extract_key_value(char *buf, unsigned int pos, char **key, char **value)
763 {
764         int key_len = 0;
765         int value_len = 0;
766
767         key_len = buf[pos];
768         pos++;
769         *key = g_strndup((const gchar *)&buf[pos], key_len);
770         pos+=(key_len + 1);
771         value_len = buf[pos];
772         pos++;
773         *value = g_strndup((const gchar *)&buf[pos], value_len);
774         pos+=value_len;
775         return pos;
776 }
777
778 static gboolean extract_request_result(char *buf, unsigned int size, char **err)
779 {
780         gboolean success = FALSE;
781         unsigned int pos = 0;
782         int type = -1;
783
784         pos = 1;
785         while (pos < size) {
786
787                 type = buf[pos];//3
788                 pos++;
789                 if (type == VICI_KEY_VALUE) {
790                         char *key = NULL;
791                         char *value = NULL;
792                         pos = extract_key_value(buf, pos, &key, &value);
793                         DBG("pos : %d size : %d\n", pos, size);
794
795                         /* TODO :remove this after debug */
796                         DBG("key : %s value : %s\n", key, value);
797                         if (g_strcmp0(key, "success") == 0)
798                                 (g_strcmp0(value, "yes") == 0)?(success = TRUE):(success = FALSE);
799
800                         if (g_strcmp0(key, "errmsg"))
801                                 *err = g_strdup(value);
802                         g_free(key);
803                         g_free(value);
804                 }
805         }
806         return success;
807 }
808
809 static int handle_vici_result(gboolean success, int cmd, char * err)
810 {
811         int ret = 0;
812         if (success)
813                 return 0;
814
815         g_free(err);
816
817         switch (cmd) {
818         case    VICI_CMD_LOAD_CONN:
819                 ret = EINVAL;
820                 break;
821         case    VICI_CMD_LOAD_SHARED:
822                 ret = EINVAL;
823                 break;
824         case    VICI_CMD_LOAD_CERT:
825                 ret = EINVAL;
826                 break;
827         case    VICI_CMD_LOAD_AUTH:
828                 ret = 0;
829                 break;
830         case    VICI_CMD_LOAD_KEY:
831                 ret = EINVAL;
832                 break;
833         case    VICI_CMD_INITIATE:
834                 ret = ECONNABORTED;
835                 break;
836         default:
837                 break;
838         }
839
840         DBG(" %s failed with %d!\n", vici_cmd_str[cmd], ret);
841         return ret;
842 }
843
844 static int process_vici_response(struct request * req)
845 {
846         char *err = NULL;
847         gboolean success = FALSE;
848         int ret = 0;
849
850         if (!req)
851                 return -1;
852
853         if (!req->rcvbuf || req->rcvbuf[0] != VICI_CMD_RESPONSE)
854                 return -1;
855
856         //TODO: remove below when there's no further problem.
857         debug_vici_message(req->rcvbuf, req->rcv_pkt_size);
858
859         success = extract_request_result(req->rcvbuf, req->rcv_pkt_size, &err);
860         ret = handle_vici_result(success, req->cmd, err);
861
862         return ret;
863 }
864
865 int vici_send_request(VICIClient *vici_client, VICIClientCmd cmd, VICISection *root)
866 {
867         struct request *req = NULL;
868         int ret;
869
870         DBG("%s", vici_cmd_str[cmd]);
871         ret = create_vici_request(VICI_CMD_REQUEST, cmd, &req);
872         if (ret < 0) {
873                 connman_error("error on create_request\n");
874                 return ret;
875         }
876
877         write_section(req, root);
878         //TODO: remove below when there's no further problem.
879         debug_vici_message(req->sndbuf + req->hdr_len - 1, req->used - req->hdr_len + 1);
880
881         ret = send_vici_command(req, vici_client);
882         if (ret < 0) {
883                 destroy_vici_request(req);
884                 connman_error("error on send_command\n");
885         }
886
887         return ret;
888 }
889
890 static int get_socket_from_source(GIOChannel *source, GIOCondition condition)
891 {
892         int sock = -1;
893         /* check socket */
894         sock = g_io_channel_unix_get_fd(source);
895         if (sock < SOCK_FD_MIN)
896                 return -1;
897
898         if ((condition & G_IO_ERR) || (condition & G_IO_HUP) || (condition & G_IO_NVAL)) {
899                 connman_error("G_IO_ERR/G_IO_HUP/G_IO_NVAL received sock [%d] condition [%d]\n", sock, condition);
900                 //TODO: handle the breaking socket
901                 return -1;
902         }
903         return sock;
904 }
905
906 static int read_socket(int sock, char *data, unsigned int data_len)
907 {
908         int rbytes = 0;
909         int total_rbytes = 0;
910
911         if (sock < SOCK_FD_MIN || !data || data_len <= 0)
912                 return -1;
913
914         while (data_len > 0) {
915                 errno = 0;
916                 rbytes = read(sock, data, data_len);
917                 if (rbytes <= 0)
918                         return -1;
919
920                 total_rbytes += rbytes;
921                 data += rbytes;
922                 data_len -= rbytes;
923         }
924
925         return total_rbytes;
926 }
927
928 static int recv_vici_pkt(int sock, struct request *req)
929 {
930         if(!req)
931                 return -1;
932
933         if (req->rcv_pkt_size == 0) {
934                 unsigned int pkt_size = 0;
935                 if (read_socket(sock, (char *)&pkt_size, sizeof(pkt_size)) < 0)
936                         return -1;
937
938                 req->rcv_pkt_size = ntohl(pkt_size);
939                 /* TODO :REMOVE THIS AFTER DEBUG */
940                 DBG("rcv_pkt_size [%d] will be recved\n", req->rcv_pkt_size);
941         } else {
942
943                 char *buf = NULL;
944                 buf = g_try_malloc0(req->rcv_pkt_size);
945                 if (buf == NULL)
946                         return -1;
947
948                 if (read_socket(sock, buf, req->rcv_pkt_size) < 0) {
949                         g_free(buf);
950                         return -1;
951                 }
952                 req->rcvbuf = buf;
953         }
954
955         return 0;
956 }
957
958 static struct request *pop_vici_request(VICIClient *vici_client)
959 {
960         GSList *list = NULL;
961
962         if (!vici_client)
963                 return NULL;
964
965         list = vici_client->request_list;
966         if(!list)
967                 return NULL;
968
969         return list->data;
970 }
971
972 static gboolean process_reply(GIOChannel *source,
973                                            GIOCondition condition,
974                                            gpointer user_data)
975 {
976         VICIClient *vici_client = NULL;
977         struct request * req = NULL;
978         int sock = 0;
979         int ret = 0;
980
981         vici_client = (VICIClient *)user_data;
982         if (!vici_client)
983                 return FALSE;
984
985         sock = get_socket_from_source(source, condition);
986         if (sock < 0)
987                 return FALSE;
988
989         /* get first request */
990         req = pop_vici_request((VICIClient *)user_data);
991         if (!req)
992                 return FALSE;
993
994         if(recv_vici_pkt(sock, req) < 0)
995                 return FALSE;
996
997         if (!req->rcvbuf) {
998                 return TRUE;
999         }
1000
1001         ret = process_vici_response(req);
1002         vici_client->request_list = g_slist_remove(vici_client->request_list, req);
1003         destroy_vici_request(req);
1004
1005         /* TODO :remove this after debug */
1006         DBG("left request reply : %d", g_slist_length(vici_client->request_list));
1007
1008         if (ret!= 0 || g_slist_length(vici_client->request_list) == 0)
1009                 vici_client->reply(ret, vici_client->ipsec_user_data);
1010
1011         return TRUE;
1012 }
1013
1014 static int str_to_socket_addr(const char *uri, struct sockaddr_un *addr)
1015 {
1016         memset(addr, 0, sizeof(*addr));
1017         addr->sun_family = AF_UNIX;
1018         strncpy(addr->sun_path, uri, sizeof(addr->sun_path));
1019
1020         addr->sun_path[sizeof(addr->sun_path)-1] = '\0';
1021
1022         return offsetof(struct sockaddr_un, sun_path) + strlen(addr->sun_path);
1023 }
1024
1025 static int connect_socket(const char *uri)
1026 {
1027         struct sockaddr_un addr;
1028         int len, fd;
1029
1030         fd = socket(AF_UNIX, SOCK_STREAM, 0);
1031         if (fd < 0) {
1032                 connman_error("socket() failed");
1033                 return -errno;
1034         }
1035
1036         len = str_to_socket_addr(uri, &addr);
1037         if (len == -1) {
1038                 connman_error("str_to_socket_addr failed");
1039                 close(fd);
1040                 return -1;
1041         }
1042
1043         if (connect(fd, (struct sockaddr*)&addr, len) < 0) {
1044                 connman_error("connect failed. errno %d/%s", errno, strerror(errno));
1045                 close(fd);
1046                 return -errno;
1047         }
1048
1049         return fd;
1050 }
1051
1052 int vici_initialize(VICIClient **vici_client)
1053 {
1054         GIOChannel *vici_channel;
1055
1056         *vici_client = g_try_new0(VICIClient, 1);
1057         if (!*vici_client) {
1058                 connman_error("out of memory");
1059                 return -ENOMEM;
1060         }
1061
1062         (*vici_client)->client_sock_fd = connect_socket(VICI_DEFAULT_URI);
1063         if ((*vici_client)->client_sock_fd < 0) {
1064                 connman_error("connect_socket failed");
1065                 g_free(*vici_client);
1066                 return -EIO;
1067         }
1068
1069         vici_channel = g_io_channel_unix_new((*vici_client)->client_sock_fd);
1070         if (!vici_channel) {
1071                 connman_error("g_io_channel_unix_new failed");
1072                 close((*vici_client)->client_sock_fd);
1073                 g_free(*vici_client);
1074                 return -ENOMEM;
1075         }
1076
1077         (*vici_client)->client_watch = g_io_add_watch_full(vici_channel,
1078                                                  G_PRIORITY_LOW,
1079                                                  G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
1080                                                  (GIOFunc)process_reply,
1081                                                  (gpointer)*vici_client,
1082                                                  NULL);
1083         g_io_channel_unref(vici_channel);
1084
1085         DBG("connected");
1086         return 0;
1087 }
1088
1089 void vici_set_connect_reply_cb(VICIClient *vici_client, vici_connect_reply_cb reply_cb, gpointer user_data)
1090 {
1091         vici_client->reply = reply_cb;
1092         vici_client->ipsec_user_data = user_data;
1093 }
1094
1095 int vici_deinitialize(VICIClient *vici_client)
1096 {
1097         if (vici_client->client_watch > 0) {
1098                 g_source_remove(vici_client->client_watch);
1099                 vici_client->client_watch = 0;
1100         }
1101
1102         close(vici_client->client_sock_fd);
1103         g_slist_free_full(vici_client->request_list, destroy_vici_request);
1104         g_free(vici_client);
1105
1106         return 0;
1107 }