DA: Skip initializing failed_bssids list when eapol failure case
[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         if (fstat(fd, &st) != 0) {
290                 connman_error("fstat failed");
291                 fclose(fp);
292                 return NULL;
293         }
294
295         file_size = st.st_size;
296         file_buff = g_try_malloc0(sizeof(char)*st.st_size);
297         if (file_buff == NULL) {
298                 connman_error("g_try_malloc0 failed\n");
299                 fclose(fp);
300                 return NULL;
301         }
302
303         if (fread(file_buff, 1, file_size, fp) != file_size) {
304                 connman_error("file size not matched\n");
305                 g_free(file_buff);
306                 file_buff = NULL;
307         }
308
309         fclose(fp);
310         return file_buff;
311 }
312
313 int vici_add_cert_kv(VICISection *section, const char *key,
314                 const char *value, const char *subsection)
315 {
316         char *cert = NULL;
317         int ret = 0;
318
319         if (value == NULL) {
320                 DBG("value is null");
321                 return 0;
322         }
323
324         cert = load_cert_from_path(value);
325         if (!cert)
326                 return -1;
327
328         ret = vici_add_kv(section, key, (const char *)cert, subsection);
329         g_free(cert);
330         return ret;
331 }
332
333 int vici_add_cert_kvl(VICISection *section, const char *key,
334                 const char *value, const char *subsection)
335 {
336         char *cert = NULL;
337         int ret = 0;
338
339         cert = load_cert_from_path(value);
340         if (!cert)
341                 return -1;
342
343         ret = vici_add_kvl(section, key, (const char *)cert, subsection);
344         g_free(cert);
345         return ret;
346 }
347
348 static void *add_element(struct request *r, enum vici_element type,
349                                                  unsigned int size)
350 {
351         unsigned int newlen;
352         void *ret, *new;
353
354         if (r->used + size + 1 > r->allocated) {
355                 newlen = r->allocated;
356                 while (newlen < r->used + size + 1) {
357                         newlen *= 2;
358                 }
359                 new = realloc(r->sndbuf, newlen);
360                 if (!new) {
361                         r->err = -errno;
362                         return NULL;
363                 }
364                 r->sndbuf = new;
365                 r->allocated = newlen;
366         }
367         r->sndbuf[r->used++] = type;
368         ret = r->sndbuf + r->used;
369         r->used += size;
370         return ret;
371 }
372
373 static void section_start(struct request *r, const char *name)
374 {
375         uint8_t nlen;
376         char *pos;
377
378         nlen = strlen(name);
379         pos = add_element(r, VICI_SECTION_START, 1 + nlen);
380         if (pos) {
381                 pos[0] = nlen;
382                 memcpy(pos + 1, name, nlen);
383         }
384 }
385
386 static void section_end(struct request *r)
387 {
388         add_element(r, VICI_SECTION_END, 0);
389 }
390
391 static void key_value(struct request *r, const char *name,
392                            const void *buf, unsigned int buflen)
393 {
394         uint8_t nlen;
395         uint16_t vlen;
396         char *pos;
397
398         nlen = strlen(name);
399         pos = add_element(r, VICI_KEY_VALUE, 1 + nlen + sizeof(vlen) + buflen);
400         if (pos) {
401                 pos[0] = nlen;
402                 memcpy(pos + 1, name, nlen);
403                 vlen = htons(buflen);
404                 memcpy(pos + 1 + nlen, &vlen, sizeof(vlen));
405                 memcpy(pos + 1 + nlen + sizeof(vlen), buf, buflen);
406         }
407 }
408
409
410 static void list_start(struct request *r, const char *name)
411 {
412         uint8_t nlen;
413         char *pos;
414
415         nlen = strlen(name);
416         pos = add_element(r, VICI_LIST_START, 1 + nlen);
417         if (pos) {
418                 pos[0] = nlen;
419                 memcpy(pos + 1, name, nlen);
420         }
421 }
422
423 static void list_item(struct request *r, const void *buf,
424                                           unsigned int buflen)
425 {
426         uint16_t vlen;
427         char *pos;
428
429         pos = add_element(r, VICI_LIST_ITEM, sizeof(vlen) + buflen);
430         if (pos) {
431                 vlen = htons(buflen);
432                 memcpy(pos, &vlen, sizeof(vlen));
433                 memcpy(pos + sizeof(vlen), buf, buflen);
434         }
435 }
436
437 static void list_end(struct request *r)
438 {
439         add_element(r, VICI_LIST_END, 0);
440 }
441
442 static void destroy_vici_request(gpointer data)
443 {
444         struct request *req = (struct request *)data;
445         if(!req)
446                 return;
447
448         g_free(req->sndbuf);
449         g_free(req);
450 }
451
452 static int create_vici_request(enum vici_packet_type type, VICIClientCmd cmd,
453                                                   struct request **rp)
454 {
455         struct request *req = NULL;
456
457         if (cmd >= VICI_CMD_MAX || !rp)
458                 return -EINVAL;
459
460         req = g_try_new0(struct request, 1);
461         if (!req) {
462                 connman_error("g_try_new0 failed");
463                 return -ENOMEM;
464         }
465
466         req->used = 2;
467         req->used += strlen(vici_cmd_str[cmd]);
468         req->allocated = MIN(32, req->used);
469         req->sndbuf = g_try_new0(char, req->allocated);
470         if (!req->sndbuf) {
471                 connman_error("g_try_new0 failed");
472                 g_free(req);
473                 return -ENOMEM;
474         }
475
476         req->sndbuf[0] = type;
477         req->sndbuf[1] = req->used - 2; /* except for type and name length */
478         memcpy(req->sndbuf + 2, vici_cmd_str[cmd], req->used - 2);
479         req->hdr_len = req->used;
480         req->cmd = cmd;
481
482         *rp = req;
483
484         return 0;
485 }
486
487 static void write_section_kvs(VICISection *section, struct request *req)
488 {
489         GHashTableIter iter;
490         gpointer key, value;
491
492         if (section == NULL || req == NULL)
493                 return;
494
495         g_hash_table_iter_init (&iter, section->kvs);
496         while (g_hash_table_iter_next (&iter, &key, &value)) {
497                 if (!key || !value)
498                         continue;
499                 key_value(req, (const char*)key, (const void *)value, strlen((char *)value));
500         }
501
502         return;
503 }
504
505 static void write_list_item(gpointer data, gpointer user_data)
506 {
507         struct request *req = NULL;
508         char *value = NULL;
509
510         if (!data || !user_data)
511                 return;
512
513         value = (char *)data;
514         req = (struct request *)user_data;
515         list_item(req, value, strlen(value));
516
517         return;
518 }
519
520 static void write_section_kvls(VICISection *section, struct request *req)
521 {
522         GHashTableIter iter;
523         gpointer key, value;
524
525         if (section == NULL || req == NULL)
526                 return;
527
528         g_hash_table_iter_init (&iter, section->kvls);
529         while (g_hash_table_iter_next (&iter, &key, &value)) {
530                 if (!key || !value)
531                         continue;
532
533                 list_start(req, key);
534                 g_slist_foreach((GSList *)value, (GFunc)write_list_item, (gpointer)req);
535                 list_end(req);
536         }
537
538         return;
539 }
540
541 static void write_section(struct request *req, VICISection *section)
542 {
543         GHashTableIter iter;
544         gpointer key, value;
545
546         if (req == NULL || section == NULL)
547                 return;
548
549         if (section->name)
550                 section_start(req, section->name);
551
552         write_section_kvs(section, req);
553         write_section_kvls(section, req);
554
555         g_hash_table_iter_init(&iter, section->subsection);
556         while (g_hash_table_iter_next (&iter, &key, &value)) {
557                 if (!key || !value)
558                         continue;
559                 write_section(req, (VICISection *)value);
560         }
561
562         if (section->name)
563                 section_end(req);
564         return;
565 }
566
567 static int check_socket(int sock)
568 {
569         struct pollfd p_fd;
570         int res = 0;
571
572         p_fd.fd = sock;
573         p_fd.events = POLLIN | POLLOUT | POLLERR | POLLHUP | POLLNVAL;
574         res = poll((struct pollfd *) &p_fd, 1, 1);
575
576         if (res < 0) {
577                 connman_error("Polling error from socket\n");
578                 return -1;
579         } else if (res == 0) {
580                 connman_error( "poll timeout. socket is busy\n");
581                 return 1;
582         } else {
583
584                 if (p_fd.revents & POLLERR) {
585                         connman_error("Error! POLLERR from socket[%d]\n", sock);
586                         return -1;
587                 } else if (p_fd.revents & POLLHUP) {
588                         connman_error("Error! POLLHUP from socket[%d]\n", sock);
589                         return -1;
590                 } else if (p_fd.revents & POLLNVAL) {
591                         connman_error("Error! POLLNVAL from socket[%d]\n", sock);
592                         return -1;
593                 } else if (p_fd.revents & POLLIN) {
594                         return 0;
595                 } else if (p_fd.revents & POLLOUT) {
596                         return 0;
597                 }
598         }
599
600         connman_error("Unknown poll event [%d]\n", p_fd.revents);
601         return -1;
602 }
603
604 static int write_socket(int sock, char *data, int data_len)
605 {
606         int wbytes = 0;
607         int left_len = data_len;
608         char *ptr = data;
609         int res = 0;
610
611         if (sock < SOCK_FD_MIN || !data || data_len < 0)
612                 return -1;
613
614         res = check_socket(sock);
615         if (res < 0)
616                 return -1;
617         else if (res > 0)
618                 return -2;
619
620         errno = 0;
621         while (left_len) {
622                 wbytes = write(sock, ptr, left_len);
623                 if (wbytes <= 0) {
624                         connman_error("Failed to write data into socket[%d].\n", sock);
625                         break;
626                 }else if (wbytes < left_len) {
627                         left_len -= wbytes;
628                         ptr += wbytes;
629                 } else if (wbytes == left_len) {
630                         left_len = 0;
631                 } else {
632                         connman_error("Unknown error occurred.\n");
633                         break;
634                 }
635         }
636
637         if (left_len)
638                 return -1;
639         else
640                 return 0;
641 }
642
643 int send_vici_command(struct request *req, VICIClient *vici_client)
644 {
645         unsigned int size = 0;
646         int sock_fd = 0;
647         int res = 0;
648
649         if (req == NULL ||  vici_client == NULL) {
650                 connman_error("request is NULL\n");
651                 return -EINVAL;
652         }
653         sock_fd = vici_client->client_sock_fd;
654
655         size = htonl(req->used);
656         res = write_socket(sock_fd, (char *)&size, sizeof(size));
657         if (res != 0) {
658                 connman_error("failed to send size with network byte order\n");
659                 return -EIO;
660         }
661
662         res = write_socket(sock_fd, req->sndbuf, req->used);
663         if (res != 0) {
664                 connman_error("failed to send pkt\n");
665                 return -EIO;
666         }
667
668         if(req->cmd != VICI_CMD_REGISTER_CHILD_UPDOWN)
669                 vici_client->request_list = g_slist_append(vici_client->request_list, req);
670
671         return res;
672 }
673
674 static void print_vici_element(int elem_type, char *value, int sections)
675 {
676         int i = 0;
677
678
679         switch (elem_type) {
680         case VICI_SECTION_START:
681                 for (i = 0; i < sections - 1; i++)
682                         DBG("\t");
683                 DBG("%s = {\n", value);
684                 break;
685         case VICI_SECTION_END:
686                 for (i = 0; i < sections; i++)
687                         DBG("\t");
688                 DBG("}\n");
689                 break;
690         case VICI_KEY_VALUE:
691                 for (i = 0; i < sections; i++)
692                         DBG("\t");
693                 DBG("%s\n", value);
694                 break;
695         case VICI_LIST_START:
696                 for (i = 0; i < sections; i++)
697                         DBG("\t");
698                 DBG("%s = [", value);
699                 break;
700         case VICI_LIST_ITEM:
701                 DBG("%s, ", value);
702                 break;
703         case VICI_LIST_END:
704                 DBG("]\n");
705                 break;
706         default:
707                 break;
708         }
709         return;
710 }
711
712 static void debug_vici_message(char *buf, unsigned int size)
713 {
714         char temp[255];
715         unsigned int pos = 0;
716         int len = 0;
717         int sections = 0;
718         int type = -1;
719
720         if (buf == NULL || size == 0)
721                 return;
722
723         pos = 1;
724         while (pos < size) {
725
726                 type = buf[pos];
727                 pos++;
728                 switch (type) {
729                 case VICI_SECTION_START:
730                 {
731                         len = buf[pos];
732                         pos++;
733                         g_strlcpy(temp, (const gchar *)&buf[pos], len + 1);
734                         pos += len;
735                         sections++;
736                 }
737                         break;
738                 case VICI_SECTION_END:
739                 {
740                         sections--;
741                 }
742                         break;
743                 case VICI_KEY_VALUE:
744                 {
745                         int key_len = 0;
746                         int value_len = 0;
747
748                         key_len = buf[pos];
749                         pos++;
750                         g_strlcpy(temp, (const gchar *)&buf[pos], key_len + 1);
751                         temp[key_len] = '=';
752                         pos += (key_len + 1);
753                         value_len = buf[pos];
754                         pos++;
755                         g_strlcpy(temp + key_len + 1, (const gchar *)&buf[pos], value_len + 1);
756                         pos += value_len;
757                 }
758                         break;
759                 case VICI_LIST_START:
760                 {
761                         len = buf[pos];
762                         pos++;
763                         g_strlcpy(temp, (const gchar *)&buf[pos], len + 1);
764                         pos += len;
765                 }
766                         break;
767                 case VICI_LIST_ITEM:
768                 {
769                         pos++;
770                         len = buf[pos];
771                         pos++;
772                         g_strlcpy(temp, (const gchar *)&buf[pos], len + 1);
773                         pos += len;
774                 }
775                         break;
776                 case VICI_LIST_END:
777                         break;
778                 default:
779                         break;
780                 }
781                 print_vici_element(type, temp, sections);
782         }
783         return;
784 }
785
786 static unsigned int extract_key_value(char *buf, unsigned int pos, char **key, char **value)
787 {
788         int key_len = 0;
789         int value_len = 0;
790
791         key_len = buf[pos];
792         pos++;
793         *key = g_strndup((const gchar *)&buf[pos], key_len);
794         pos+=(key_len + 1);
795         value_len = buf[pos];
796         pos++;
797         *value = g_strndup((const gchar *)&buf[pos], value_len);
798         pos+=value_len;
799         return pos;
800 }
801
802 static gboolean extract_request_result(char *buf, unsigned int size, char **err)
803 {
804         gboolean success = FALSE;
805         unsigned int pos = 0;
806         int type = -1;
807
808         pos = 1;
809         while (pos < size) {
810
811                 type = buf[pos];//3
812                 pos++;
813                 if (type == VICI_KEY_VALUE) {
814                         char *key = NULL;
815                         char *value = NULL;
816                         pos = extract_key_value(buf, pos, &key, &value);
817                         DBG("pos : %d size : %d\n", pos, size);
818
819                         /* TODO :remove this after debug */
820                         DBG("key : %s value : %s\n", key, value);
821                         if (g_strcmp0(key, "success") == 0)
822                                 (g_strcmp0(value, "yes") == 0)?(success = TRUE):(success = FALSE);
823
824                         if (g_strcmp0(key, "errmsg"))
825                                 *err = g_strdup(value);
826                         g_free(key);
827                         g_free(value);
828                 }
829         }
830         return success;
831 }
832
833 static int handle_vici_result(gboolean success, int cmd, char * err)
834 {
835         int ret = 0;
836         if (success)
837                 return 0;
838
839         g_free(err);
840
841         switch (cmd) {
842         case    VICI_CMD_LOAD_CONN:
843                 ret = EINVAL;
844                 break;
845         case    VICI_CMD_LOAD_SHARED:
846                 ret = EINVAL;
847                 break;
848         case    VICI_CMD_LOAD_CERT:
849                 ret = EINVAL;
850                 break;
851         case    VICI_CMD_LOAD_AUTH:
852                 ret = 0;
853                 break;
854         case    VICI_CMD_LOAD_KEY:
855                 ret = EINVAL;
856                 break;
857         case    VICI_CMD_INITIATE:
858                 ret = ECONNABORTED;
859                 break;
860         case    VICI_CMD_TERMINATE:
861                 ret = EINVAL;
862                 break;
863         default:
864                 break;
865         }
866
867         DBG(" %s failed with %d!\n", vici_cmd_str[cmd], ret);
868         return ret;
869 }
870
871 static int process_vici_response(struct request * req)
872 {
873         char *err = NULL;
874         gboolean success = FALSE;
875         int ret = 0;
876
877         if (!req)
878                 return -1;
879
880         if (!req->rcvbuf || req->rcvbuf[0] != VICI_CMD_RESPONSE)
881                 return -1;
882
883         //TODO: remove below when there's no further problem.
884         debug_vici_message(req->rcvbuf, req->rcv_pkt_size);
885
886         success = extract_request_result(req->rcvbuf, req->rcv_pkt_size, &err);
887         ret = handle_vici_result(success, req->cmd, err);
888
889         return ret;
890 }
891
892 int vici_send_request(VICIClient *vici_client, VICIClientCmd cmd, VICISection *root)
893 {
894         struct request *req = NULL;
895         int ret;
896
897         DBG("%s", vici_cmd_str[cmd]);
898         ret = create_vici_request(VICI_CMD_REQUEST, cmd, &req);
899         if (ret < 0) {
900                 connman_error("error on create_request\n");
901                 return ret;
902         }
903
904         write_section(req, root);
905         //TODO: remove below when there's no further problem.
906         debug_vici_message(req->sndbuf + req->hdr_len - 1, req->used - req->hdr_len + 1);
907
908         ret = send_vici_command(req, vici_client);
909         if (ret < 0) {
910                 destroy_vici_request(req);
911                 connman_error("error on send_command\n");
912         }
913
914         return ret;
915 }
916
917
918 int vici_set_event_cb(VICIClient *vici_client, vici_event_cb cb, gpointer user_data)
919 {
920         struct request *req = NULL;
921         int ret;
922
923         DBG("%s",vici_cmd_str[VICI_EVENT_CHILD_UP]);
924         ret = create_vici_request(VICI_EVENT_REGISTER, VICI_CMD_REGISTER_CHILD_UPDOWN, &req);
925         if (ret < 0) {
926                 connman_error("error on create_request\n");
927                 return ret;
928         }
929
930         ret = send_vici_command(req, vici_client);
931         if (ret < 0) {
932                 connman_error("error on send_command\n");
933         }
934
935         destroy_vici_request(req);
936         vici_client->event_cb = cb;
937         vici_client->event_user_data = user_data;
938
939         return ret;
940
941 }
942
943 static int get_socket_from_source(GIOChannel *source, GIOCondition condition)
944 {
945         int sock = -1;
946         /* check socket */
947         sock = g_io_channel_unix_get_fd(source);
948         if (sock < SOCK_FD_MIN)
949                 return -1;
950
951         if ((condition & G_IO_ERR) || (condition & G_IO_HUP) || (condition & G_IO_NVAL)) {
952                 connman_error("G_IO_ERR/G_IO_HUP/G_IO_NVAL received sock [%d] condition [%d]\n", sock, condition);
953                 //TODO: handle the breaking socket
954                 return -1;
955         }
956         return sock;
957 }
958
959 static int read_socket(int sock, char *data, unsigned int data_len)
960 {
961         int rbytes = 0;
962         int total_rbytes = 0;
963
964         if (sock < SOCK_FD_MIN || !data || data_len <= 0)
965                 return -1;
966
967         while (data_len > 0) {
968                 errno = 0;
969                 rbytes = read(sock, data, data_len);
970                 if (rbytes <= 0)
971                         return -1;
972
973                 total_rbytes += rbytes;
974                 data += rbytes;
975                 data_len -= rbytes;
976         }
977
978         return total_rbytes;
979 }
980
981 static int recv_vici_pkt(int sock, struct _VICIClient *vici_client)
982 {
983         if(!vici_client)
984                 return -1;
985
986         if (vici_client->rcv_pkt_size == 0) {
987                 unsigned int pkt_size = 0;
988                 if (read_socket(sock, (char *)&pkt_size, sizeof(pkt_size)) < 0)
989                         return -1;
990
991                 vici_client->rcv_pkt_size = ntohl(pkt_size);
992                 /* TODO :REMOVE THIS AFTER DEBUG */
993                 DBG("rcv_pkt_size [%d] will be recved\n", vici_client->rcv_pkt_size);
994         } else {
995
996                 DBG("rcv_pkt_size [%d] is recved\n", vici_client->rcv_pkt_size);
997                 char *buf = NULL;
998                 buf = g_try_malloc0(vici_client->rcv_pkt_size);
999                 if (buf == NULL)
1000                         return -1;
1001
1002                 if (read_socket(sock, buf, vici_client->rcv_pkt_size) < 0) {
1003                         g_free(buf);
1004                         return -1;
1005                 }
1006                 vici_client->rcvbuf = buf;
1007         }
1008
1009         return 0;
1010 }
1011
1012 static struct request *pop_vici_request(VICIClient *vici_client)
1013 {
1014         GSList *list = NULL;
1015
1016         if (!vici_client)
1017                 return NULL;
1018
1019         list = vici_client->request_list;
1020         if(!list)
1021                 return NULL;
1022
1023         return list->data;
1024 }
1025
1026 static void process_vici_reply(VICIClient *vici_client)
1027 {
1028         struct request *req;
1029         int ret = 0;
1030
1031         if (!vici_client)
1032                 return;
1033
1034         /* get first request */
1035         req = pop_vici_request(vici_client);
1036         if (!req)
1037                 return;
1038
1039         req->rcvbuf = vici_client->rcvbuf;
1040         req->rcv_pkt_size = vici_client->rcv_pkt_size;
1041
1042         ret = process_vici_response(req);
1043         vici_client->request_list = g_slist_remove(vici_client->request_list, req);
1044         destroy_vici_request(req);
1045
1046         /* TODO :remove this after debug */
1047         DBG("left request reply : %d", g_slist_length(vici_client->request_list));
1048
1049         if (ret != 0 || g_slist_length(vici_client->request_list) == 0)
1050                 vici_client->reply_cb(ret, vici_client->reply_user_data);
1051
1052 }
1053
1054 static int extract_event_name(char *buf, unsigned int size, char *temp)
1055 {
1056         int pos = 1;
1057         int name_len = 0;
1058         name_len = buf[pos];
1059         pos++;
1060         DBG("event len: %d", name_len);
1061         while(pos <  size && pos - 2 < name_len) {
1062                 temp[pos - 2] = buf[pos];
1063                 pos++;
1064         }
1065         temp[pos] = '\0';
1066         DBG("event name: %s", temp);
1067         return pos;
1068 }
1069
1070 static char *vici_get_value(char *buf, unsigned int pos, unsigned int size, char *search_key)
1071 {
1072         int type = -1;
1073
1074         pos = 1;
1075         while (pos < size) {
1076
1077                 type = buf[pos];//3
1078                 pos++;
1079                 if (type == VICI_KEY_VALUE) {
1080                         char *key = NULL;
1081                         char *value = NULL;
1082                         pos = extract_key_value(buf, pos, &key, &value);
1083                         if (g_strcmp0(search_key, key) == 0) {
1084                                 g_free(key);
1085                                 return value;
1086                         }
1087
1088                         g_free(key);
1089                         g_free(value);
1090                 }
1091         }
1092         return NULL;
1093 }
1094
1095 static void process_child_updown(VICIClient *vici_client,char *buf, unsigned int size)
1096 {
1097         char *state = NULL;
1098
1099         state = vici_get_value(buf, 0, size, "state");
1100         if (g_strcmp0(state, "ESTABLISHED") == 0) {
1101                 DBG("ESTABLISHED");
1102                 vici_client->event_cb(VICI_EVENT_CHILD_UP, vici_client->event_user_data);
1103         } else if (g_strcmp0(state, "DELETING") == 0) {
1104                 DBG("DELETING");
1105                 vici_client->event_cb(VICI_EVENT_CHILD_DOWN, vici_client->event_user_data);
1106         } else {
1107                 DBG("Unknown event");
1108         }
1109         g_free(state);
1110         return;
1111 }
1112
1113 static void process_vici_event(VICIClient *vici_client)
1114 {
1115         char *buf = NULL;
1116         unsigned int size = 0;
1117         unsigned int pos = 0;
1118         char temp[256] = {0,};
1119         if (!vici_client || !(vici_client->rcvbuf) || vici_client->rcv_pkt_size == 0)
1120                 return;
1121
1122         buf = vici_client->rcvbuf;
1123         size = vici_client->rcv_pkt_size;
1124
1125         pos = extract_event_name(buf, size, temp);
1126         /* TODO: remove below after debug */
1127         /* add parser */
1128         if (g_strcmp0(temp, "child-updown") == 0)
1129                 process_child_updown(vici_client, buf + pos -1, size - pos);
1130 }
1131
1132 static void process_vici_packet(VICIClient *vici_client, char *buf)
1133 {
1134
1135         if (!vici_client || !buf)
1136                 return;
1137
1138         if (buf[0] == VICI_CMD_RESPONSE) {
1139                 DBG("VICI_CMD_RESPONSE\n");
1140                 process_vici_reply(vici_client);
1141         } else if (buf[0] == VICI_EVENT_CONFIRM) {
1142                 DBG("VICI_EVENT_CONFIRM\n");
1143         } else if (buf[0] == VICI_EVENT) {
1144                 DBG("VICI_EVENT");
1145                 process_vici_event(vici_client);
1146         } else {
1147                 DBG("Not handled [%u]", buf[0]);
1148         }
1149         return;
1150 }
1151
1152 static gboolean process_vici_msg(GIOChannel *source,
1153                                            GIOCondition condition,
1154                                            gpointer user_data)
1155 {
1156         VICIClient *vici_client = NULL;
1157         int sock = 0;
1158
1159         vici_client = (VICIClient *)user_data;
1160         if (!vici_client)
1161                 return FALSE;
1162
1163         sock = get_socket_from_source(source, condition);
1164         if (sock < 0)
1165                 return FALSE;
1166
1167
1168         if(recv_vici_pkt(sock, vici_client) < 0)
1169                 return FALSE;
1170
1171         if (!vici_client->rcvbuf) {
1172                 return TRUE;
1173         }
1174
1175         process_vici_packet(vici_client, vici_client->rcvbuf);
1176         g_free(vici_client->rcvbuf);
1177         vici_client->rcvbuf = NULL;
1178         vici_client->rcv_pkt_size = 0;
1179
1180         return TRUE;
1181 }
1182
1183 static int str_to_socket_addr(const char *uri, struct sockaddr_un *addr)
1184 {
1185         memset(addr, 0, sizeof(*addr));
1186         addr->sun_family = AF_UNIX;
1187         strncpy(addr->sun_path, uri, sizeof(addr->sun_path));
1188
1189         addr->sun_path[sizeof(addr->sun_path)-1] = '\0';
1190
1191         return offsetof(struct sockaddr_un, sun_path) + strlen(addr->sun_path);
1192 }
1193
1194 static int connect_socket(const char *uri)
1195 {
1196         struct sockaddr_un addr;
1197         int len, fd;
1198
1199         fd = socket(AF_UNIX, SOCK_STREAM, 0);
1200         if (fd < 0) {
1201                 connman_error("socket() failed");
1202                 return -errno;
1203         }
1204
1205         len = str_to_socket_addr(uri, &addr);
1206         if (len == -1) {
1207                 connman_error("str_to_socket_addr failed");
1208                 close(fd);
1209                 return -1;
1210         }
1211
1212         if (connect(fd, (struct sockaddr*)&addr, len) < 0) {
1213                 connman_error("connect failed. errno %d/%s", errno, strerror(errno));
1214                 close(fd);
1215                 return -errno;
1216         }
1217
1218         return fd;
1219 }
1220
1221 static int initialize_vici_source(VICIClient *vici_client)
1222 {
1223         GIOChannel *vici_channel;
1224         if (!vici_client) {
1225                 return -ENOMEM;
1226         }
1227
1228         vici_client->client_sock_fd = connect_socket(VICI_DEFAULT_URI);
1229         if (vici_client->client_sock_fd < 0) {
1230                 connman_error("connect_socket failed");
1231                 return -EIO;
1232         }
1233
1234         vici_channel = g_io_channel_unix_new(vici_client->client_sock_fd);
1235         if (!vici_channel) {
1236                 connman_error("g_io_channel_unix_new failed");
1237                 close(vici_client->client_sock_fd);
1238                 return -ENOMEM;
1239         }
1240
1241         vici_client->client_watch = g_io_add_watch_full(vici_channel,
1242                                                  G_PRIORITY_LOW,
1243                                                  G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
1244                                                  (GIOFunc)process_vici_msg,
1245                                                  (gpointer)vici_client,
1246                                                  NULL);
1247         g_io_channel_unref(vici_channel);
1248         return 0;
1249 }
1250
1251 int vici_initialize(VICIClient **vici_client)
1252 {
1253         int ret = 0;
1254
1255         *vici_client = g_try_new0(VICIClient, 1);
1256         if (!*vici_client) {
1257                 connman_error("out of memory");
1258                 return -ENOMEM;
1259         }
1260
1261         ret = initialize_vici_source(*vici_client);
1262         if (ret != 0) {
1263                 g_free(*vici_client);
1264                 return ret;
1265         }
1266
1267         DBG("connected");
1268         return 0;
1269 }
1270
1271 void vici_set_request_reply_cb(VICIClient *vici_client, vici_request_reply_cb reply_cb, gpointer user_data)
1272 {
1273         vici_client->reply_cb = reply_cb;
1274         vici_client->reply_user_data = user_data;
1275 }
1276
1277 int vici_deinitialize(VICIClient *vici_client)
1278 {
1279         if (vici_client->client_watch > 0) {
1280                 g_source_remove(vici_client->client_watch);
1281                 vici_client->client_watch = 0;
1282         }
1283
1284         close(vici_client->client_sock_fd);
1285         g_slist_free_full(vici_client->request_list, destroy_vici_request);
1286         g_free(vici_client->rcvbuf);
1287         g_free(vici_client);
1288
1289         return 0;
1290 }