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.
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.
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
28 #include <sys/socket.h>
31 #include <arpa/inet.h>
35 #include <connman/log.h>
37 #include "vici-client.h"
40 #define VICI_REQUEST_TIMEOUT 5000
44 VICI_SECTION_START = 1,
52 enum vici_packet_type {
54 VICI_CMD_RESPONSE = 1,
56 VICI_EVENT_REGISTER = 3,
57 VICI_EVENT_UNREGISTER = 4,
58 VICI_EVENT_CONFIRM = 5,
59 VICI_EVENT_UNKNOWN = 6,
63 static const char *vici_cmd_str[] = {
75 unsigned int allocated;
82 unsigned int rcv_pkt_size;
93 vici_connect_reply_cb reply;
94 void *ipsec_user_data;
101 GHashTable *subsection;
104 static void remove_list(gpointer data)
109 g_slist_free_full((GSList *)data, g_free);
112 void vici_destroy_section(VICISection* section)
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);
121 static void free_section(gpointer data)
123 VICISection* section = (VICISection*)data;
124 vici_destroy_section(section);
127 VICISection* vici_create_section(const char* name)
129 VICISection* section;
131 section = g_try_new0(VICISection, 1);
133 connman_error("Failed to create section");
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);
145 int add_subsection(const char* name, VICISection* child, VICISection* section)
147 if (section == NULL || name == NULL || child == NULL) {
148 connman_error("invalid parameter");
152 g_hash_table_insert(section->subsection, g_strdup(name), child);
156 static int add_kvl_to_section(const char* key, const char* value, VICISection* section)
159 if (section == NULL || key == NULL || value == NULL) {
160 connman_error("invalid parameter");
164 list = g_hash_table_lookup(section->kvls, key);
166 list = g_slist_alloc();
168 list = g_slist_prepend(list, g_strdup(value));
169 g_hash_table_replace(section->kvls, g_strdup(key), list);
173 static int add_kv_to_section(const char* key, const char* value, VICISection* section)
175 if (section == NULL || key == NULL || value == NULL) {
176 connman_error("invalid parameter");
180 g_hash_table_insert(section->kvs, g_strdup(key), g_strdup(value));
184 static VICISection* get_subsection(VICISection* section, const char* name)
186 VICISection* sub = g_hash_table_lookup(section->subsection, name);
188 sub = vici_create_section(name);
189 add_subsection(name, sub, section);
194 int vici_add_kv(VICISection* section, const char* key,
195 const char* value, const char* subsection)
197 VICISection* target = section;
198 DBG("key: %s, value: %s, subsection: %s", key, value, subsection);
200 if (section == NULL || key == NULL) {
201 connman_error("invalid parameter");
206 target = get_subsection(section, subsection);
208 add_kv_to_section(key, value, target);
212 int vici_add_kvl(VICISection* section, const char* key,
213 const char* value, const char* subsection)
215 VICISection* target = section;
217 DBG("key: %s, value: %s, subsection: %s", key, value, subsection);
218 if (section == NULL || key == NULL) {
219 connman_error("invalid parameter");
224 target = get_subsection(section, subsection);
226 if (g_strcmp0(subsection, "children") == 0)
227 target = get_subsection(target, "net");
229 add_kvl_to_section(key, value, target);
233 static void add_list_to_section(char *key, GSList *list, VICISection *section)
235 if (section == NULL || key == NULL || list == NULL)
238 g_hash_table_insert(section->kvls, g_strdup(key), g_slist_copy(list));
242 int vici_add_list(VICISection* section, char *key, GSList *list, const char* subsection)
244 VICISection* target = section;
246 DBG("key: %s, subsection: %s", key, subsection);
247 if (section == NULL || key == NULL) {
248 connman_error("invalid parameter");
253 target = get_subsection(section, subsection);
255 if (g_strcmp0(subsection, "children") == 0)
256 target = get_subsection(target, "net");
258 add_list_to_section(key, list, target);
262 static char *load_cert_from_path(const char *path)
267 size_t file_size = 0;
268 char *file_buff = NULL;
270 fp = fopen(path, "rb");
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");
281 if (fread(file_buff, 1, file_size, fp) != file_size) {
282 connman_error("file size not matched\n");
291 int vici_add_cert_kv(VICISection *section, const char *key,
292 const char *value, const char *subsection)
298 DBG("value is null");
302 cert = load_cert_from_path(value);
306 ret = vici_add_kv(section, key, (const char *)cert, subsection);
311 int vici_add_cert_kvl(VICISection *section, const char *key,
312 const char *value, const char *subsection)
317 cert = load_cert_from_path(value);
321 ret = vici_add_kvl(section, key, (const char *)cert, subsection);
326 static void *add_element(struct request *r, enum vici_element type,
332 if (r->used + size + 1 > r->allocated) {
333 newlen = r->allocated;
334 while (newlen < r->used + size + 1) {
337 new = realloc(r->sndbuf, newlen);
343 r->allocated = newlen;
345 r->sndbuf[r->used++] = type;
346 ret = r->sndbuf + r->used;
351 static void section_start(struct request *r, const char *name)
357 pos = add_element(r, VICI_SECTION_START, 1 + nlen);
360 memcpy(pos + 1, name, nlen);
364 static void section_end(struct request *r)
366 add_element(r, VICI_SECTION_END, 0);
369 static void key_value(struct request *r, const char *name,
370 const void *buf, unsigned int buflen)
377 pos = add_element(r, VICI_KEY_VALUE, 1 + nlen + sizeof(vlen) + buflen);
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);
388 static void list_start(struct request *r, const char *name)
394 pos = add_element(r, VICI_LIST_START, 1 + nlen);
397 memcpy(pos + 1, name, nlen);
401 static void list_item(struct request *r, const void *buf,
407 pos = add_element(r, VICI_LIST_ITEM, sizeof(vlen) + buflen);
409 vlen = htons(buflen);
410 memcpy(pos, &vlen, sizeof(vlen));
411 memcpy(pos + sizeof(vlen), buf, buflen);
415 static void list_end(struct request *r)
417 add_element(r, VICI_LIST_END, 0);
420 static void destroy_vici_request(gpointer data)
422 struct request *req = (struct request *)data;
431 static int create_vici_request(enum vici_packet_type type, VICIClientCmd cmd,
434 struct request *req = NULL;
436 if (cmd >= VICI_CMD_MAX || !rp)
439 req = g_try_new0(struct request, 1);
441 connman_error("g_try_new0 failed");
446 req->used += strlen(vici_cmd_str[cmd]);
447 req->allocated = MIN(32, req->used);
448 req->sndbuf = g_try_new0(char, req->allocated);
450 connman_error("g_try_new0 failed");
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;
466 static void write_section_kvs(VICISection *section, struct request *req)
471 if (section == NULL || req == NULL)
474 g_hash_table_iter_init (&iter, section->kvs);
475 while (g_hash_table_iter_next (&iter, &key, &value)) {
478 key_value(req, (const char*)key, (const void *)value, strlen((char *)value));
484 static void write_list_item(gpointer data, gpointer user_data)
486 struct request *req = NULL;
489 if (!data || !user_data)
492 value = (char *)data;
493 req = (struct request *)user_data;
494 list_item(req, value, strlen(value));
499 static void write_section_kvls(VICISection *section, struct request *req)
504 if (section == NULL || req == NULL)
507 g_hash_table_iter_init (&iter, section->kvls);
508 while (g_hash_table_iter_next (&iter, &key, &value)) {
512 list_start(req, key);
513 g_slist_foreach((GSList *)value, (GFunc)write_list_item, (gpointer)req);
520 static void write_section(struct request *req, VICISection *section)
525 if (req == NULL || section == NULL)
529 section_start(req, section->name);
531 write_section_kvs(section, req);
532 write_section_kvls(section, req);
534 g_hash_table_iter_init(&iter, section->subsection);
535 while (g_hash_table_iter_next (&iter, &key, &value)) {
538 write_section(req, (VICISection *)value);
546 static int check_socket(int sock)
552 p_fd.events = POLLIN | POLLOUT | POLLERR | POLLHUP | POLLNVAL;
553 res = poll((struct pollfd *) &p_fd, 1, 1);
556 connman_error("Polling error from socket\n");
558 } else if (res == 0) {
559 connman_error( "poll timeout. socket is busy\n");
563 if (p_fd.revents & POLLERR) {
564 connman_error("Error! POLLERR from socket[%d]\n", sock);
566 } else if (p_fd.revents & POLLHUP) {
567 connman_error("Error! POLLHUP from socket[%d]\n", sock);
569 } else if (p_fd.revents & POLLNVAL) {
570 connman_error("Error! POLLNVAL from socket[%d]\n", sock);
572 } else if (p_fd.revents & POLLIN) {
574 } else if (p_fd.revents & POLLOUT) {
579 connman_error("Unknown poll event [%d]\n", p_fd.revents);
583 static int write_socket(int sock, char *data, int data_len)
586 int left_len = data_len;
590 if (sock < SOCK_FD_MIN || !data || data_len < 0)
593 res = check_socket(sock);
601 wbytes = write(sock, ptr, left_len);
603 connman_error("Failed to write data into socket[%d].\n", sock);
605 }else if (wbytes < left_len) {
608 } else if (wbytes == left_len) {
611 connman_error("Unknown error occurred.\n");
622 int send_vici_command(struct request *req, VICIClient *vici_client)
624 unsigned int size = 0;
628 connman_error("request is NULL\n");
632 size = htonl(req->used);
633 res = write_socket(vici_client->client_sock_fd, (char *)&size, sizeof(size));
635 connman_error("failed to send size with network byte order\n");
639 res = write_socket(vici_client->client_sock_fd, req->sndbuf, req->used);
641 connman_error("failed to send pkt\n");
645 vici_client->request_list = g_slist_append(vici_client->request_list, req);
649 static void print_vici_element(int elem_type, char *value, int sections)
655 case VICI_SECTION_START:
656 for (i = 0; i < sections - 1; i++)
658 DBG("%s = {\n", value);
660 case VICI_SECTION_END:
661 for (i = 0; i < sections; i++)
666 for (i = 0; i < sections; i++)
670 case VICI_LIST_START:
671 for (i = 0; i < sections; i++)
673 DBG("%s = [", value);
687 static void debug_vici_message(char *buf, unsigned int size)
690 unsigned int pos = 0;
695 if (buf == NULL || size == 0)
704 case VICI_SECTION_START:
708 g_strlcpy(temp, (const gchar *)&buf[pos], len + 1);
713 case VICI_SECTION_END:
725 g_strlcpy(temp, (const gchar *)&buf[pos], key_len + 1);
727 pos += (key_len + 1);
728 value_len = buf[pos];
730 g_strlcpy(temp + key_len + 1, (const gchar *)&buf[pos], value_len + 1);
732 len = key_len + 1 + value_len;
735 case VICI_LIST_START:
739 g_strlcpy(temp, (const gchar *)&buf[pos], len + 1);
748 g_strlcpy(temp, (const gchar *)&buf[pos], len + 1);
757 print_vici_element(type, temp, sections);
762 static unsigned int extract_key_value(char *buf, unsigned int pos, char **key, char **value)
769 *key = g_strndup((const gchar *)&buf[pos], key_len);
771 value_len = buf[pos];
773 *value = g_strndup((const gchar *)&buf[pos], value_len);
778 static gboolean extract_request_result(char *buf, unsigned int size, char **err)
780 gboolean success = FALSE;
781 unsigned int pos = 0;
789 if (type == VICI_KEY_VALUE) {
792 pos = extract_key_value(buf, pos, &key, &value);
793 DBG("pos : %d size : %d\n", pos, size);
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);
800 if (g_strcmp0(key, "errmsg"))
801 *err = g_strdup(value);
809 static int handle_vici_result(gboolean success, int cmd, char * err)
818 case VICI_CMD_LOAD_CONN:
821 case VICI_CMD_LOAD_SHARED:
824 case VICI_CMD_LOAD_CERT:
827 case VICI_CMD_LOAD_AUTH:
830 case VICI_CMD_LOAD_KEY:
833 case VICI_CMD_INITIATE:
840 DBG(" %s failed with %d!\n", vici_cmd_str[cmd], ret);
844 static int process_vici_response(struct request * req)
847 gboolean success = FALSE;
853 if (!req->rcvbuf || req->rcvbuf[0] != VICI_CMD_RESPONSE)
856 //TODO: remove below when there's no further problem.
857 debug_vici_message(req->rcvbuf, req->rcv_pkt_size);
859 success = extract_request_result(req->rcvbuf, req->rcv_pkt_size, &err);
860 ret = handle_vici_result(success, req->cmd, err);
865 int vici_send_request(VICIClient *vici_client, VICIClientCmd cmd, VICISection *root)
867 struct request *req = NULL;
870 DBG("%s", vici_cmd_str[cmd]);
871 ret = create_vici_request(VICI_CMD_REQUEST, cmd, &req);
873 connman_error("error on create_request\n");
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);
881 ret = send_vici_command(req, vici_client);
883 destroy_vici_request(req);
884 connman_error("error on send_command\n");
890 static int get_socket_from_source(GIOChannel *source, GIOCondition condition)
894 sock = g_io_channel_unix_get_fd(source);
895 if (sock < SOCK_FD_MIN)
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
906 static int read_socket(int sock, char *data, unsigned int data_len)
909 int total_rbytes = 0;
911 if (sock < SOCK_FD_MIN || !data || data_len <= 0)
914 while (data_len > 0) {
916 rbytes = read(sock, data, data_len);
920 total_rbytes += rbytes;
928 static int recv_vici_pkt(int sock, struct request *req)
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)
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);
944 buf = g_try_malloc0(req->rcv_pkt_size);
948 if (read_socket(sock, buf, req->rcv_pkt_size) < 0) {
958 static struct request *pop_vici_request(VICIClient *vici_client)
965 list = vici_client->request_list;
972 static gboolean process_reply(GIOChannel *source,
973 GIOCondition condition,
976 VICIClient *vici_client = NULL;
977 struct request * req = NULL;
981 vici_client = (VICIClient *)user_data;
985 sock = get_socket_from_source(source, condition);
989 /* get first request */
990 req = pop_vici_request((VICIClient *)user_data);
994 if(recv_vici_pkt(sock, req) < 0)
1001 ret = process_vici_response(req);
1002 vici_client->request_list = g_slist_remove(vici_client->request_list, req);
1003 destroy_vici_request(req);
1005 /* TODO :remove this after debug */
1006 DBG("left request reply : %d", g_slist_length(vici_client->request_list));
1008 if (ret!= 0 || g_slist_length(vici_client->request_list) == 0)
1009 vici_client->reply(ret, vici_client->ipsec_user_data);
1014 static int str_to_socket_addr(const char *uri, struct sockaddr_un *addr)
1016 memset(addr, 0, sizeof(*addr));
1017 addr->sun_family = AF_UNIX;
1018 strncpy(addr->sun_path, uri, sizeof(addr->sun_path));
1020 addr->sun_path[sizeof(addr->sun_path)-1] = '\0';
1022 return offsetof(struct sockaddr_un, sun_path) + strlen(addr->sun_path);
1025 static int connect_socket(const char *uri)
1027 struct sockaddr_un addr;
1030 fd = socket(AF_UNIX, SOCK_STREAM, 0);
1032 connman_error("socket() failed");
1036 len = str_to_socket_addr(uri, &addr);
1038 connman_error("str_to_socket_addr failed");
1043 if (connect(fd, (struct sockaddr*)&addr, len) < 0) {
1044 connman_error("connect failed. errno %d/%s", errno, strerror(errno));
1052 int vici_initialize(VICIClient **vici_client)
1054 GIOChannel *vici_channel;
1056 *vici_client = g_try_new0(VICIClient, 1);
1057 if (!*vici_client) {
1058 connman_error("out of memory");
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);
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);
1077 (*vici_client)->client_watch = g_io_add_watch_full(vici_channel,
1079 G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
1080 (GIOFunc)process_reply,
1081 (gpointer)*vici_client,
1083 g_io_channel_unref(vici_channel);
1089 void vici_set_connect_reply_cb(VICIClient *vici_client, vici_connect_reply_cb reply_cb, gpointer user_data)
1091 vici_client->reply = reply_cb;
1092 vici_client->ipsec_user_data = user_data;
1095 int vici_deinitialize(VICIClient *vici_client)
1097 if (vici_client->client_watch > 0) {
1098 g_source_remove(vici_client->client_watch);
1099 vici_client->client_watch = 0;
1102 close(vici_client->client_sock_fd);
1103 g_slist_free_full(vici_client->request_list, destroy_vici_request);
1104 g_free(vici_client);