Merge "@fix: Disconnect Reason code was not getting reset" 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                 }
753                         break;
754                 case VICI_LIST_START:
755                 {
756                         len = buf[pos];
757                         pos++;
758                         g_strlcpy(temp, (const gchar *)&buf[pos], len + 1);
759                         pos += len;
760                 }
761                         break;
762                 case VICI_LIST_ITEM:
763                 {
764                         pos++;
765                         len = buf[pos];
766                         pos++;
767                         g_strlcpy(temp, (const gchar *)&buf[pos], len + 1);
768                         pos += len;
769                 }
770                         break;
771                 case VICI_LIST_END:
772                         break;
773                 default:
774                         break;
775                 }
776                 print_vici_element(type, temp, sections);
777         }
778         return;
779 }
780
781 static unsigned int extract_key_value(char *buf, unsigned int pos, char **key, char **value)
782 {
783         int key_len = 0;
784         int value_len = 0;
785
786         key_len = buf[pos];
787         pos++;
788         *key = g_strndup((const gchar *)&buf[pos], key_len);
789         pos+=(key_len + 1);
790         value_len = buf[pos];
791         pos++;
792         *value = g_strndup((const gchar *)&buf[pos], value_len);
793         pos+=value_len;
794         return pos;
795 }
796
797 static gboolean extract_request_result(char *buf, unsigned int size, char **err)
798 {
799         gboolean success = FALSE;
800         unsigned int pos = 0;
801         int type = -1;
802
803         pos = 1;
804         while (pos < size) {
805
806                 type = buf[pos];//3
807                 pos++;
808                 if (type == VICI_KEY_VALUE) {
809                         char *key = NULL;
810                         char *value = NULL;
811                         pos = extract_key_value(buf, pos, &key, &value);
812                         DBG("pos : %d size : %d\n", pos, size);
813
814                         /* TODO :remove this after debug */
815                         DBG("key : %s value : %s\n", key, value);
816                         if (g_strcmp0(key, "success") == 0)
817                                 (g_strcmp0(value, "yes") == 0)?(success = TRUE):(success = FALSE);
818
819                         if (g_strcmp0(key, "errmsg"))
820                                 *err = g_strdup(value);
821                         g_free(key);
822                         g_free(value);
823                 }
824         }
825         return success;
826 }
827
828 static int handle_vici_result(gboolean success, int cmd, char * err)
829 {
830         int ret = 0;
831         if (success)
832                 return 0;
833
834         g_free(err);
835
836         switch (cmd) {
837         case    VICI_CMD_LOAD_CONN:
838                 ret = EINVAL;
839                 break;
840         case    VICI_CMD_LOAD_SHARED:
841                 ret = EINVAL;
842                 break;
843         case    VICI_CMD_LOAD_CERT:
844                 ret = EINVAL;
845                 break;
846         case    VICI_CMD_LOAD_AUTH:
847                 ret = 0;
848                 break;
849         case    VICI_CMD_LOAD_KEY:
850                 ret = EINVAL;
851                 break;
852         case    VICI_CMD_INITIATE:
853                 ret = ECONNABORTED;
854                 break;
855         case    VICI_CMD_TERMINATE:
856                 ret = EINVAL;
857                 break;
858         default:
859                 break;
860         }
861
862         DBG(" %s failed with %d!\n", vici_cmd_str[cmd], ret);
863         return ret;
864 }
865
866 static int process_vici_response(struct request * req)
867 {
868         char *err = NULL;
869         gboolean success = FALSE;
870         int ret = 0;
871
872         if (!req)
873                 return -1;
874
875         if (!req->rcvbuf || req->rcvbuf[0] != VICI_CMD_RESPONSE)
876                 return -1;
877
878         //TODO: remove below when there's no further problem.
879         debug_vici_message(req->rcvbuf, req->rcv_pkt_size);
880
881         success = extract_request_result(req->rcvbuf, req->rcv_pkt_size, &err);
882         ret = handle_vici_result(success, req->cmd, err);
883
884         return ret;
885 }
886
887 int vici_send_request(VICIClient *vici_client, VICIClientCmd cmd, VICISection *root)
888 {
889         struct request *req = NULL;
890         int ret;
891
892         DBG("%s", vici_cmd_str[cmd]);
893         ret = create_vici_request(VICI_CMD_REQUEST, cmd, &req);
894         if (ret < 0) {
895                 connman_error("error on create_request\n");
896                 return ret;
897         }
898
899         write_section(req, root);
900         //TODO: remove below when there's no further problem.
901         debug_vici_message(req->sndbuf + req->hdr_len - 1, req->used - req->hdr_len + 1);
902
903         ret = send_vici_command(req, vici_client);
904         if (ret < 0) {
905                 destroy_vici_request(req);
906                 connman_error("error on send_command\n");
907         }
908
909         return ret;
910 }
911
912
913 int vici_set_event_cb(VICIClient *vici_client, vici_event_cb cb, gpointer user_data)
914 {
915         struct request *req = NULL;
916         int ret;
917
918         DBG("%s",vici_cmd_str[VICI_EVENT_CHILD_UP]);
919         ret = create_vici_request(VICI_EVENT_REGISTER, VICI_CMD_REGISTER_CHILD_UPDOWN, &req);
920         if (ret < 0) {
921                 connman_error("error on create_request\n");
922                 return ret;
923         }
924
925         ret = send_vici_command(req, vici_client);
926         if (ret < 0) {
927                 connman_error("error on send_command\n");
928         }
929
930         destroy_vici_request(req);
931         vici_client->event_cb = cb;
932         vici_client->event_user_data = user_data;
933
934         return ret;
935
936 }
937
938 static int get_socket_from_source(GIOChannel *source, GIOCondition condition)
939 {
940         int sock = -1;
941         /* check socket */
942         sock = g_io_channel_unix_get_fd(source);
943         if (sock < SOCK_FD_MIN)
944                 return -1;
945
946         if ((condition & G_IO_ERR) || (condition & G_IO_HUP) || (condition & G_IO_NVAL)) {
947                 connman_error("G_IO_ERR/G_IO_HUP/G_IO_NVAL received sock [%d] condition [%d]\n", sock, condition);
948                 //TODO: handle the breaking socket
949                 return -1;
950         }
951         return sock;
952 }
953
954 static int read_socket(int sock, char *data, unsigned int data_len)
955 {
956         int rbytes = 0;
957         int total_rbytes = 0;
958
959         if (sock < SOCK_FD_MIN || !data || data_len <= 0)
960                 return -1;
961
962         while (data_len > 0) {
963                 errno = 0;
964                 rbytes = read(sock, data, data_len);
965                 if (rbytes <= 0)
966                         return -1;
967
968                 total_rbytes += rbytes;
969                 data += rbytes;
970                 data_len -= rbytes;
971         }
972
973         return total_rbytes;
974 }
975
976 static int recv_vici_pkt(int sock, struct _VICIClient *vici_client)
977 {
978         if(!vici_client)
979                 return -1;
980
981         if (vici_client->rcv_pkt_size == 0) {
982                 unsigned int pkt_size = 0;
983                 if (read_socket(sock, (char *)&pkt_size, sizeof(pkt_size)) < 0)
984                         return -1;
985
986                 vici_client->rcv_pkt_size = ntohl(pkt_size);
987                 /* TODO :REMOVE THIS AFTER DEBUG */
988                 DBG("rcv_pkt_size [%d] will be recved\n", vici_client->rcv_pkt_size);
989         } else {
990
991                 DBG("rcv_pkt_size [%d] is recved\n", vici_client->rcv_pkt_size);
992                 char *buf = NULL;
993                 buf = g_try_malloc0(vici_client->rcv_pkt_size);
994                 if (buf == NULL)
995                         return -1;
996
997                 if (read_socket(sock, buf, vici_client->rcv_pkt_size) < 0) {
998                         g_free(buf);
999                         return -1;
1000                 }
1001                 vici_client->rcvbuf = buf;
1002         }
1003
1004         return 0;
1005 }
1006
1007 static struct request *pop_vici_request(VICIClient *vici_client)
1008 {
1009         GSList *list = NULL;
1010
1011         if (!vici_client)
1012                 return NULL;
1013
1014         list = vici_client->request_list;
1015         if(!list)
1016                 return NULL;
1017
1018         return list->data;
1019 }
1020
1021 static void process_vici_reply(VICIClient *vici_client)
1022 {
1023         struct request *req;
1024         int ret = 0;
1025
1026         if (!vici_client)
1027                 return;
1028
1029         /* get first request */
1030         req = pop_vici_request(vici_client);
1031         if (!req)
1032                 return;
1033
1034         req->rcvbuf = vici_client->rcvbuf;
1035         req->rcv_pkt_size = vici_client->rcv_pkt_size;
1036
1037         ret = process_vici_response(req);
1038         vici_client->request_list = g_slist_remove(vici_client->request_list, req);
1039         destroy_vici_request(req);
1040
1041         /* TODO :remove this after debug */
1042         DBG("left request reply : %d", g_slist_length(vici_client->request_list));
1043
1044         if (ret != 0 || g_slist_length(vici_client->request_list) == 0)
1045                 vici_client->reply_cb(ret, vici_client->reply_user_data);
1046
1047 }
1048
1049 static int extract_event_name(char *buf, unsigned int size, char *temp)
1050 {
1051         int pos = 1;
1052         int name_len = 0;
1053         name_len = buf[pos];
1054         pos++;
1055         DBG("event len: %d", name_len);
1056         while(pos <  size && pos - 2 < name_len) {
1057                 temp[pos - 2] = buf[pos];
1058                 pos++;
1059         }
1060         temp[pos] = '\0';
1061         DBG("event name: %s", temp);
1062         return pos;
1063 }
1064
1065 static char *vici_get_value(char *buf, unsigned int pos, unsigned int size, char *search_key)
1066 {
1067         int type = -1;
1068
1069         pos = 1;
1070         while (pos < size) {
1071
1072                 type = buf[pos];//3
1073                 pos++;
1074                 if (type == VICI_KEY_VALUE) {
1075                         char *key = NULL;
1076                         char *value = NULL;
1077                         pos = extract_key_value(buf, pos, &key, &value);
1078                         if (g_strcmp0(search_key, key) == 0) {
1079                                 g_free(key);
1080                                 return value;
1081                         }
1082
1083                         g_free(key);
1084                         g_free(value);
1085                 }
1086         }
1087         return NULL;
1088 }
1089
1090 static void process_child_updown(VICIClient *vici_client,char *buf, unsigned int size)
1091 {
1092         char *state = NULL;
1093
1094         state = vici_get_value(buf, 0, size, "state");
1095         if (g_strcmp0(state, "ESTABLISHED") == 0) {
1096                 DBG("ESTABLISHED");
1097                 vici_client->event_cb(VICI_EVENT_CHILD_UP, vici_client->event_user_data);
1098         } else if (g_strcmp0(state, "DELETING") == 0) {
1099                 DBG("DELETING");
1100                 vici_client->event_cb(VICI_EVENT_CHILD_DOWN, vici_client->event_user_data);
1101         } else {
1102                 DBG("Unknown event");
1103         }
1104         g_free(state);
1105         return;
1106 }
1107
1108 static void process_vici_event(VICIClient *vici_client)
1109 {
1110         char *buf = NULL;
1111         unsigned int size = 0;
1112         unsigned int pos = 0;
1113         char temp[256] = {0,};
1114         if (!vici_client || !(vici_client->rcvbuf) || vici_client->rcv_pkt_size == 0)
1115                 return;
1116
1117         buf = vici_client->rcvbuf;
1118         size = vici_client->rcv_pkt_size;
1119
1120         pos = extract_event_name(buf, size, temp);
1121         /* TODO: remove below after debug */
1122         /* add parser */
1123         if (g_strcmp0(temp, "child-updown") == 0)
1124                 process_child_updown(vici_client, buf + pos -1, size - pos);
1125 }
1126
1127 static void process_vici_packet(VICIClient *vici_client, char *buf)
1128 {
1129
1130         if (!vici_client || !buf)
1131                 return;
1132
1133         if (buf[0] == VICI_CMD_RESPONSE) {
1134                 DBG("VICI_CMD_RESPONSE\n");
1135                 process_vici_reply(vici_client);
1136         } else if (buf[0] == VICI_EVENT_CONFIRM) {
1137                 DBG("VICI_EVENT_CONFIRM\n");
1138         } else if (buf[0] == VICI_EVENT) {
1139                 DBG("VICI_EVENT");
1140                 process_vici_event(vici_client);
1141         } else {
1142                 DBG("Not handled [%u]", buf[0]);
1143         }
1144         return;
1145 }
1146
1147 static gboolean process_vici_msg(GIOChannel *source,
1148                                            GIOCondition condition,
1149                                            gpointer user_data)
1150 {
1151         VICIClient *vici_client = NULL;
1152         int sock = 0;
1153
1154         vici_client = (VICIClient *)user_data;
1155         if (!vici_client)
1156                 return FALSE;
1157
1158         sock = get_socket_from_source(source, condition);
1159         if (sock < 0)
1160                 return FALSE;
1161
1162
1163         if(recv_vici_pkt(sock, vici_client) < 0)
1164                 return FALSE;
1165
1166         if (!vici_client->rcvbuf) {
1167                 return TRUE;
1168         }
1169
1170         process_vici_packet(vici_client, vici_client->rcvbuf);
1171         g_free(vici_client->rcvbuf);
1172         vici_client->rcvbuf = NULL;
1173         vici_client->rcv_pkt_size = 0;
1174
1175         return TRUE;
1176 }
1177
1178 static int str_to_socket_addr(const char *uri, struct sockaddr_un *addr)
1179 {
1180         memset(addr, 0, sizeof(*addr));
1181         addr->sun_family = AF_UNIX;
1182         strncpy(addr->sun_path, uri, sizeof(addr->sun_path));
1183
1184         addr->sun_path[sizeof(addr->sun_path)-1] = '\0';
1185
1186         return offsetof(struct sockaddr_un, sun_path) + strlen(addr->sun_path);
1187 }
1188
1189 static int connect_socket(const char *uri)
1190 {
1191         struct sockaddr_un addr;
1192         int len, fd;
1193
1194         fd = socket(AF_UNIX, SOCK_STREAM, 0);
1195         if (fd < 0) {
1196                 connman_error("socket() failed");
1197                 return -errno;
1198         }
1199
1200         len = str_to_socket_addr(uri, &addr);
1201         if (len == -1) {
1202                 connman_error("str_to_socket_addr failed");
1203                 close(fd);
1204                 return -1;
1205         }
1206
1207         if (connect(fd, (struct sockaddr*)&addr, len) < 0) {
1208                 connman_error("connect failed. errno %d/%s", errno, strerror(errno));
1209                 close(fd);
1210                 return -errno;
1211         }
1212
1213         return fd;
1214 }
1215
1216 static int initialize_vici_source(VICIClient *vici_client)
1217 {
1218         GIOChannel *vici_channel;
1219         if (!vici_client) {
1220                 return -ENOMEM;
1221         }
1222
1223         vici_client->client_sock_fd = connect_socket(VICI_DEFAULT_URI);
1224         if (vici_client->client_sock_fd < 0) {
1225                 connman_error("connect_socket failed");
1226                 return -EIO;
1227         }
1228
1229         vici_channel = g_io_channel_unix_new(vici_client->client_sock_fd);
1230         if (!vici_channel) {
1231                 connman_error("g_io_channel_unix_new failed");
1232                 close(vici_client->client_sock_fd);
1233                 return -ENOMEM;
1234         }
1235
1236         vici_client->client_watch = g_io_add_watch_full(vici_channel,
1237                                                  G_PRIORITY_LOW,
1238                                                  G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
1239                                                  (GIOFunc)process_vici_msg,
1240                                                  (gpointer)vici_client,
1241                                                  NULL);
1242         g_io_channel_unref(vici_channel);
1243         return 0;
1244 }
1245
1246 int vici_initialize(VICIClient **vici_client)
1247 {
1248         int ret = 0;
1249
1250         *vici_client = g_try_new0(VICIClient, 1);
1251         if (!*vici_client) {
1252                 connman_error("out of memory");
1253                 return -ENOMEM;
1254         }
1255
1256         ret = initialize_vici_source(*vici_client);
1257         if (ret != 0) {
1258                 g_free(*vici_client);
1259                 return ret;
1260         }
1261
1262         DBG("connected");
1263         return 0;
1264 }
1265
1266 void vici_set_request_reply_cb(VICIClient *vici_client, vici_request_reply_cb reply_cb, gpointer user_data)
1267 {
1268         vici_client->reply_cb = reply_cb;
1269         vici_client->reply_user_data = user_data;
1270 }
1271
1272 int vici_deinitialize(VICIClient *vici_client)
1273 {
1274         if (vici_client->client_watch > 0) {
1275                 g_source_remove(vici_client->client_watch);
1276                 vici_client->client_watch = 0;
1277         }
1278
1279         close(vici_client->client_sock_fd);
1280         g_slist_free_full(vici_client->request_list, destroy_vici_request);
1281         g_free(vici_client->rcvbuf);
1282         g_free(vici_client);
1283
1284         return 0;
1285 }