--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include <errno.h>
+#include <unistd.h>
+#include <limits.h>
+#include <poll.h>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+#include <arpa/inet.h>
+
+#include <glib.h>
+
+/* Compile Flags */
+
+#define ENABLE_DEBUG_MODE_DEBUG 1
+
+/* global utils */
+
+#define MAX_SIZE_ERROR_BUFFER 256
+#define MAX_STD_INPUT_BUF 1024
+
+#define SOCK_FD_MIN 3
+#define VICI_REQUEST_TIMEOUT 5000
+
+#define VICI_DEFAULT_URI "/var/run/charon.vici"
+
+#define RESET_COLOR "\e[m"
+#define MAKE_RED "\e[31m"
+#define MAKE_GREEN "\e[32m"
+
+#if 0
+#define __FUNC_ENTER__ printf("%s() entering...\n", __func__)
+#define __FUNC_EXIT__ printf("%s() leaving...\n", __func__)
+#else
+#define __FUNC_ENTER__
+#define __FUNC_EXIT__
+#endif
+
+/* loop data */
+
+GMainLoop *main_loop;
+
+
+/* setting data */
+
+#define STRONGSWAN_CONF_PATH "./server.conf"
+#define CONF_GROUP_NAME "strongswan"
+
+typedef enum {
+ IPSEC_HYBRID_RSA,
+ IPSEC_XAUTH_PSK,
+ IPSEC_XAUTH_RSA,
+ IPSEC_IKEV2_PSK,
+ IPSEC_IKEV2_RSA,
+} ipsec_type_e;
+
+struct {
+ int type;
+ const char *type_str;
+} ipsec_type_str[] =
+{
+ {IPSEC_HYBRID_RSA, "IPSEC_HYBRID_RSA"},
+ {IPSEC_XAUTH_PSK, "IPSEC_XAUTH_PSK"},
+ {IPSEC_XAUTH_RSA, "IPSEC_XAUTH_RSA"},
+ {IPSEC_IKEV2_PSK, "IPSEC_IKEV2_PSK"},
+ {IPSEC_IKEV2_RSA, "IPSEC_IKEV2_RSA"},
+};
+
+enum strongswan_conf_key {
+ STRONGSWAN_CONF_KEY_NONE,
+ LOCAL_IP,
+ LOCAL_TS,
+ CERT_PATH,
+ CA_CERT_PATH,
+ PRIVATE_PATH,
+ IKE_DATA,
+ IKE_OWNER,
+ XAUTH_DATA,
+ XAUTH_OWNER,
+ HYBRID_POOL,
+ XAUTH_PSK_POOL,
+ XAUTH_RSA__POOL,
+ IKEV2_PSK_POOL,
+ IKEV2_RSA_POOL,
+ STRONGSWAN_CONF_KEY_MAX,
+};
+
+struct key_value {
+ int key;
+ const char *key_name;
+ char *value;
+} strongswan_conf[] = {
+ {STRONGSWAN_CONF_KEY_NONE, NULL, NULL},
+ {LOCAL_IP, "local_ip", NULL},
+ {LOCAL_TS, "local_ts", NULL},
+ {CERT_PATH, "cert_path", NULL},
+ {CA_CERT_PATH, "ca_cert_path", NULL},
+ {PRIVATE_PATH, "private_path", NULL},
+ {IKE_DATA, "ike_data", NULL},
+ {IKE_OWNER, "ike_owner", NULL},
+ {XAUTH_DATA, "xauth_data", NULL},
+ {XAUTH_OWNER, "xauth_owner", NULL},
+ {HYBRID_POOL, "hybrid_pool", NULL},
+ {XAUTH_PSK_POOL, "xauth_psk_pool", NULL},
+ {XAUTH_RSA__POOL, "xauth_rsa_pool", NULL},
+ {IKEV2_PSK_POOL, "ikev2_psk_pool", NULL},
+ {IKEV2_RSA_POOL, "ikev2_rsa_pool", NULL},
+};
+
+GKeyFile *g_conf_key_file;
+
+/* socket data */
+
+enum vici_packet_type {
+ VICI_CMD_REQUEST = 0,
+ VICI_CMD_RESPONSE = 1,
+ VICI_CMD_UNKNOWN = 2,
+ VICI_EVENT_REGISTER = 3,
+ VICI_EVENT_UNREGISTER = 4,
+ VICI_EVENT_CONFIRM = 5,
+ VICI_EVENT_UNKNOWN = 6,
+ VICI_EVENT = 7,
+};
+
+int g_client_sock;
+
+unsigned int g_pkt_size = 0;
+
+/* req data */
+
+typedef void (*process_return)(unsigned char *buf, unsigned int size);
+
+struct request {
+ unsigned int allocated;
+ unsigned int used;
+ unsigned int hdr_len;
+ char *buf;
+ int err;
+ /* io data */
+ int client_sock;
+ int client_source_sock_id;
+ int client_source_idle_id;
+ int client_source_timeout_id;
+ /* process reply */
+ unsigned int rcv_pkt_size;
+ process_return handler;
+ /* davici_cb cb; */
+ void *user;
+};
+
+GSList *g_req_list = NULL;
+
+/* message data */
+
+enum vici_element {
+ /** valid end of message */
+ VICI_END = 0,
+ /** begin of a section */
+ VICI_SECTION_START = 1,
+ /** end of a section */
+ VICI_SECTION_END = 2,
+ /** key/value pair */
+ VICI_KEY_VALUE = 3,
+ /** begin of a list */
+ VICI_LIST_START = 4,
+ /** list item */
+ VICI_LIST_ITEM = 5,
+ /** end of a list */
+ VICI_LIST_END = 6,
+};
+
+GSList *msg_list = NULL;
+
+/* declaration */
+
+void __process_packet(unsigned char *buf, unsigned int size);
+
+
+/* sock func */
+
+static int __str_to_sock_addr(const char *uri, struct sockaddr_un *addr)
+{
+ memset(addr, 0, sizeof(*addr));
+ addr->sun_family = AF_UNIX;
+ strncpy(addr->sun_path, uri, sizeof(addr->sun_path));
+
+ addr->sun_path[sizeof(addr->sun_path)-1] = '\0';
+
+ return offsetof(struct sockaddr_un, sun_path) + strlen(addr->sun_path);
+}
+
+static int __check_socket(int sock)
+{
+ struct pollfd p_fd;
+ char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
+ int res = 0;
+
+ p_fd.fd = sock;
+ p_fd.events = POLLIN | POLLOUT | POLLERR | POLLHUP | POLLNVAL;
+ res = poll((struct pollfd *) &p_fd, 1, 1);
+
+ if (res < 0) {
+ strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
+ printf("Polling error from socket[%d]. [%s]\n", sock, error_buf);
+ return -1;
+ } else if (res == 0) {
+ printf( "poll timeout. socket is busy\n");
+ return 1;
+ } else {
+
+ if (p_fd.revents & POLLERR) {
+ printf("Error! POLLERR from socket[%d]\n", sock);
+ return -1;
+ } else if (p_fd.revents & POLLHUP) {
+ printf("Error! POLLHUP from socket[%d]\n", sock);
+ return -1;
+ } else if (p_fd.revents & POLLNVAL) {
+ printf("Error! POLLNVAL from socket[%d]\n", sock);
+ return -1;
+ } else if (p_fd.revents & POLLIN) {
+#ifdef ENABLE_DEBUG_MODE_INFO
+ printf("POLLIN from socket [%d]\n", sock);
+#endif
+ return 0;
+ } else if (p_fd.revents & POLLOUT) {
+#ifdef ENABLE_DEBUG_MODE_INFO
+ printf("POLLOUT from socket [%d]\n", sock);
+#endif
+ return 0;
+ }
+ }
+
+ printf("Unknown poll event [%d]\n", p_fd.revents);
+ return -1;
+}
+
+static int __write_sock(int sock, char *data, int data_len)
+{
+ char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
+ int wbytes = 0;
+ int left_len = data_len;
+ char *ptr = data;
+ int res = 0;
+
+ if (sock < SOCK_FD_MIN || !data || data_len < 0) {
+ printf("Invalid parameter\n");
+ return -1;
+ }
+
+ res = __check_socket(sock);
+ if (res < 0) {
+ printf("Socket error\n");
+ return -1;
+ } else if (res > 0) {
+ printf("Socket is busy\n");
+ return -2;
+ }
+
+ errno = 0;
+ while (left_len) {
+ wbytes = write(sock, ptr, left_len);
+ if (wbytes <= 0) {
+ strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
+ printf("Failed to write data into socket[%d]. [error=%s]\n", sock, error_buf);
+ break;
+ }else if (wbytes < left_len) {
+#ifdef ENABLE_DEBUG_MODE_INFO
+ printf("%d bytes left. Continue sending...\n", left_len - wbytes);
+#endif
+ left_len -= wbytes;
+ ptr += wbytes;
+ } else if (wbytes == left_len) {
+#ifdef ENABLE_DEBUG_MODE_INFO
+ printf("Succeeded to write data[%d bytes] into socket [%d]\n", wbytes, sock);
+#endif
+ left_len = 0;
+ } else {
+ strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
+ printf("Unknown error occurred. [%s]\n", error_buf);
+ break;
+ }
+ }
+
+ if (left_len)
+ return -1;
+ else
+ return 0;
+}
+
+static int __read_sock(int sock, unsigned char *data, unsigned int data_len)
+{
+ int rbytes = 0;
+ int total_rbytes = 0;
+
+ if (sock < SOCK_FD_MIN || !data || data_len <= 0) {
+ printf("Invalid parameter\n");
+ return -1;
+ }
+
+
+ while (data_len > 0) {
+ errno = 0;
+ rbytes = read(sock, data, data_len);
+ printf("read [%d]\n", rbytes);
+ if (rbytes <= 0) {
+ printf("Failed to read data from socket[%d]\n", sock);
+ return -1;
+ }
+ total_rbytes += rbytes;
+ data += rbytes;
+ data_len -= rbytes;
+#ifdef ENABLE_DEBUG_MODE_INFO
+ printf("data_len %u total_rbytes %d rbytes %d\n", data_len, total_rbytes, rbytes);
+#endif
+ }
+
+#ifdef ENABLE_DEBUG_MODE_INFO
+ printf("exit while data_len %u total_rbytes %d rbytes %d\n", data_len, total_rbytes, rbytes);
+#endif
+ return total_rbytes;
+}
+
+int connect_sock(const char *uri)
+{
+ struct sockaddr_un addr;
+ char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
+ int len, fd;
+
+ len = __str_to_sock_addr(uri, &addr);
+ if (len == -1)
+ {
+ printf("invalid stream URI: '%s'", uri);
+ return -1;
+ }
+
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (fd < 0) {
+ strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
+ printf("Failed to get socket. [%s]\n", error_buf);
+ return -1;
+ }
+
+ if (connect(fd, (struct sockaddr*)&addr, len) < 0) {
+ strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
+ printf("Failed to connect client. [%s]\n", error_buf);
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+}
+
+void disconnect()
+{
+ GSList *list = NULL;
+ struct request *req = NULL;
+
+ printf("list length [%d]\n", g_slist_length(g_req_list));
+
+ for (list = g_req_list; list != NULL; list = list->next) {
+ req = list->data;
+ if (req == NULL)
+ continue;
+
+#ifdef ENABLE_DEBUG_MODE_INFO
+ printf("destroy_request [%s]\n", req->buf + 2);
+#endif
+ g_req_list = g_slist_remove(g_req_list, req);
+ g_free(req->buf);
+ g_free(req);
+ req = NULL;
+ }
+ close(g_client_sock);
+}
+
+/* req func */
+
+void destroy_request(gpointer user_data)
+{
+ struct request *req = NULL;
+ req = (struct request *)user_data;
+ if (!req) {
+ printf("Invalid parameter\n");
+ return;
+ }
+
+#ifdef ENABLE_DEBUG_MODE_INFO
+ printf("destroy_request [%s]\n", req->buf + 2);
+#endif
+ g_req_list = g_slist_remove(g_req_list, req);
+ close(req->client_sock);
+ g_free(req->buf);
+ g_free(req);
+ req = NULL;
+ return;
+}
+
+gboolean end_connect(gpointer user_data)
+{
+ disconnect();
+ return FALSE;
+}
+
+gboolean send_request(gpointer user_data)
+{
+ struct request *req = NULL;
+ unsigned int size = 0;
+ int res = 0;
+
+ req = (struct request *)user_data;
+ if (req == NULL) {
+ printf("request is NULL\n");
+ return FALSE;
+ }
+
+ printf("send_request [%s]\n", req->buf + 2);
+ size = htonl(req->used);
+ res = __write_sock(g_client_sock, (unsigned char *)&size, sizeof(size));
+ if (res != 0) {
+ printf("failed to send size with network byte order\n");
+ }
+
+ res = __write_sock(g_client_sock, req->buf, req->used);
+ if (res != 0) {
+ printf("failed to send pkt\n");
+ }
+
+ return FALSE;
+}
+
+static void* add_element(struct request *r, enum vici_element type,
+ unsigned int size)
+{
+ unsigned int newlen;
+ void *ret, *new;
+
+ if (r->used + size + 1 > r->allocated)
+ {
+ newlen = r->allocated;
+ while (newlen < r->used + size + 1)
+ {
+ newlen *= 2;
+ }
+ new = realloc(r->buf, newlen);
+ if (!new)
+ {
+ r->err = -errno;
+ return NULL;
+ }
+ r->buf = new;
+ r->allocated = newlen;
+ }
+ r->buf[r->used++] = type;
+ ret = r->buf + r->used;
+ r->used += size;
+ return ret;
+}
+
+void vici_section_start(struct request *r, const char *name)
+{
+ uint8_t nlen;
+ char *pos;
+
+ nlen = strlen(name);
+ pos = add_element(r, VICI_SECTION_START, 1 + nlen);
+ if (pos)
+ {
+ pos[0] = nlen;
+ memcpy(pos + 1, name, nlen);
+ }
+}
+
+void vici_section_end(struct request *r)
+{
+ add_element(r, VICI_SECTION_END, 0);
+}
+
+void vici_kv(struct request *r, const char *name,
+ const void *buf, unsigned int buflen)
+{
+ uint8_t nlen;
+ uint16_t vlen;
+ char *pos;
+
+ nlen = strlen(name);
+ pos = add_element(r, VICI_KEY_VALUE, 1 + nlen + sizeof(vlen) + buflen);
+ if (pos)
+ {
+ pos[0] = nlen;
+ memcpy(pos + 1, name, nlen);
+ vlen = htons(buflen);
+ memcpy(pos + 1 + nlen, &vlen, sizeof(vlen));
+ memcpy(pos + 1 + nlen + sizeof(vlen), buf, buflen);
+ }
+}
+
+
+void vici_list_start(struct request *r, const char *name)
+{
+ uint8_t nlen;
+ char *pos;
+
+ nlen = strlen(name);
+ pos = add_element(r, VICI_LIST_START, 1 + nlen);
+ if (pos)
+ {
+ pos[0] = nlen;
+ memcpy(pos + 1, name, nlen);
+ }
+}
+
+void vici_list_item(struct request *r, const void *buf,
+ unsigned int buflen)
+{
+ uint16_t vlen;
+ char *pos;
+
+ pos = add_element(r, VICI_LIST_ITEM, sizeof(vlen) + buflen);
+ if (pos)
+ {
+ vlen = htons(buflen);
+ memcpy(pos, &vlen, sizeof(vlen));
+ memcpy(pos + sizeof(vlen), buf, buflen);
+ }
+}
+
+void vici_list_end(struct request *r)
+{
+ add_element(r, VICI_LIST_END, 0);
+}
+
+int create_request(enum vici_packet_type type, const char *name,
+ struct request **rp)
+{
+ struct request *req;
+ char error_buf[MAX_SIZE_ERROR_BUFFER] = {0, };
+ int err;
+ __FUNC_ENTER__;
+
+ if (!name || !rp) {
+ printf("Invalid parameter\n");
+ return -1;
+ }
+
+ req = (struct request *)g_try_malloc0(sizeof(*req));
+ if (!req) {
+ strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
+ printf("Failed allocate memory. [%s]\n", error_buf);
+ return -1;
+ }
+
+ req->used = 2;
+ req->used += strlen(name);
+ req->allocated = MIN(32, req->used);
+ req->buf = (char *)g_try_malloc0(req->allocated);
+ if (!req->buf) {
+ strerror_r(errno, error_buf, MAX_SIZE_ERROR_BUFFER);
+ printf("Failed allocate memory. [%s]\n", error_buf);
+ g_free(req);
+ return -1;
+ }
+ req->buf[0] = type;
+ req->buf[1] = req->used - 2; /* except for type and name length */
+ memcpy(req->buf + 2, name, req->used - 2);
+ req->hdr_len = req->used;
+
+ req->handler = __process_packet;
+
+ req->client_sock = connect_sock(VICI_DEFAULT_URI);
+ if (req->client_sock <= 0) {
+ printf("error on connect_sock\n");
+ g_free(req);
+ return -1;
+ }
+
+ *rp = req;
+ g_req_list = g_slist_append(g_req_list, req);
+
+ __FUNC_EXIT__;
+ return 0;
+}
+
+/* need to add several functionalities */
+
+void __process_message(int elem_type, char *value, int sections)
+{
+ int i = 0;
+
+ switch(elem_type) {
+ case VICI_SECTION_START:
+ {
+ for (i = 0; i < sections - 1; i++)
+ printf("\t");
+ printf("%s = {\n", value);
+ }
+ break;
+ case VICI_SECTION_END:
+ {
+ for (i = 0; i < sections; i++)
+ printf("\t");
+ printf("}\n");
+ }
+ break;
+ case VICI_KEY_VALUE:
+ {
+ for (i = 0; i < sections; i++)
+ printf("\t");
+ printf("%s\n", value);
+ }
+ break;
+ case VICI_LIST_START:
+ {
+ for (i = 0; i < sections; i++)
+ printf("\t");
+ printf("%s = [", value);
+ }
+ break;
+ case VICI_LIST_ITEM:
+ {
+ printf("%s, ", value);
+ }
+ break;
+ case VICI_LIST_END:
+ {
+ printf("]\n");
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void __process_response(unsigned char *buf, unsigned int size)
+{
+ struct request *req = NULL;
+ char temp[255];
+ unsigned int pos = 0;
+ int len = 0;
+ int sections = 0;
+ int list_elems = 0;
+ int type = -1;
+
+ if (buf == NULL || size == 0)
+ return;
+
+ pos = 1;
+ while (pos < size) {
+
+ type = buf[pos];
+ pos++;
+ switch (type) {
+ case VICI_SECTION_START:
+ {
+ len = buf[pos];
+ pos++;
+ g_strlcpy(temp, (const gchar *)&buf[pos], len + 1);
+ pos+=len;
+ sections++;
+ }
+ break;
+ case VICI_SECTION_END:
+ {
+ sections--;
+ }
+ break;
+ case VICI_KEY_VALUE:
+ {
+ int key_len = 0;
+ int value_len = 0;
+
+ key_len = buf[pos];
+ pos++;
+ g_strlcpy(temp, (const gchar *)&buf[pos], key_len + 1);
+ temp[key_len] = '=';
+ pos+=(key_len + 1);
+ value_len = buf[pos];
+ pos++;
+ g_strlcpy(temp + key_len + 1, (const gchar *)&buf[pos], value_len + 1);
+ pos+=value_len;
+ len = key_len + 1 + value_len;
+ }
+ break;
+ case VICI_LIST_START:
+ {
+ len = buf[pos];
+ pos++;
+ g_strlcpy(temp, (const gchar *)&buf[pos], len + 1);
+ pos+=len;
+ }
+ break;
+ case VICI_LIST_ITEM:
+ {
+ pos++;
+ len = buf[pos];
+ pos++;
+ g_strlcpy(temp, (const gchar *)&buf[pos], len + 1);
+ pos+=len;
+ }
+ break;
+ case VICI_LIST_END:
+ {
+ }
+ break;
+ default:
+ break;
+ }
+ __process_message(type, temp, sections);
+ }
+ printf("end process\n");
+ return;
+}
+
+
+void __process_packet(unsigned char *buf, unsigned int size)
+{
+
+ int i = 0;
+
+#ifdef ENABLE_DEBUG_MODE_INFO
+ for (i = 0; i < size; i++)
+ printf("%02x ", buf[i]);
+ printf("\n");
+#endif
+ switch (buf[0])
+ {
+ case VICI_CMD_REQUEST:
+ {
+ printf("VICI_CMD_REQUEST\n");
+ }
+ break;
+ case VICI_CMD_RESPONSE:
+ {
+ printf("VICI_CMD_RESPONSE\n");
+ __process_response(buf, size);
+ }
+ break;
+ case VICI_CMD_UNKNOWN:
+ {
+ printf("VICI_CMD_UNKNOWN\n");
+ }
+ break;
+ case VICI_EVENT_REGISTER:
+ {
+ printf("VICI_EVENT_REGISTER\n");
+ }
+ break;
+ case VICI_EVENT_UNREGISTER:
+ {
+ printf("VICI_EVENT_UNREGISTER\n");
+ }
+ break;
+ case VICI_EVENT_CONFIRM:
+ {
+ printf("VICI_EVENT_CONFIRM\n");
+ }
+ break;
+ case VICI_EVENT_UNKNOWN:
+ {
+ printf("VICI_EVENT_UNKNOWN\n");
+ }
+ break;
+ case VICI_EVENT:
+ {
+ printf("VICI_EVENT\n");
+ }
+ break;
+ default:
+ printf("default\n");
+ break;
+ }
+ return;
+}
+
+
+/* glib2.0-IO function */
+
+int send_request_gio(GIOFunc process_reply, GSourceFunc send_request, GSourceFunc destroy_req, gpointer user_data);
+
+gboolean destroy_source_gio(gpointer user_data);
+gboolean send_request_gio_in_idle(gpointer user_data);
+static gboolean process_gio_source_sock(GIOChannel *source,
+ GIOCondition condition,
+ gpointer user_data);
+
+int send_request_gio(GIOFunc process_reply, GSourceFunc send_request, GSourceFunc destroy_req_gio, gpointer user_data)
+{
+ struct request *req = NULL;
+ int ret = 0;
+ __FUNC_ENTER__;
+
+ req = (struct request *)user_data;
+ if (!req) {
+ printf("Invalid parameter\n");
+ return -1;
+ }
+ GIOChannel *gio = g_io_channel_unix_new(req->client_sock);
+ req->client_source_sock_id = g_io_add_watch_full(gio,
+ G_PRIORITY_LOW,
+ G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+ (GIOFunc)process_reply,
+ (gpointer)req,
+ NULL);
+ g_io_channel_unref(gio);
+
+ req->client_source_idle_id = g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, (GSourceFunc)send_request,
+ (gpointer)req, NULL);
+
+ /* TODO: think more on destroy function */
+ req->client_source_timeout_id = g_timeout_add(VICI_REQUEST_TIMEOUT, (GSourceFunc)destroy_req_gio, (gpointer)req);
+
+ __FUNC_EXIT__;
+ return ret;
+}
+
+gboolean destroy_source_gio(gpointer user_data)
+{
+ struct request *req = NULL;
+ __FUNC_ENTER__;
+
+ req = (struct request *)user_data;
+ if (!req) {
+ printf("Invalid parameter\n");
+ return FALSE;
+ }
+
+ if (req->client_source_idle_id != 0)
+ g_source_remove(req->client_source_idle_id);
+ if (req->client_source_sock_id != 0)
+ g_source_remove(req->client_source_sock_id);
+ g_source_remove(req->client_source_timeout_id);
+ destroy_request(req);
+
+ __FUNC_EXIT__;
+ return FALSE;
+}
+
+gboolean send_request_gio_in_idle(gpointer user_data)
+{
+ struct request *req = NULL;
+ unsigned int size = 0;
+ int res = 0;
+ __FUNC_ENTER__;
+
+ req = (struct request *)user_data;
+ if (req == NULL) {
+ printf("request is NULL\n");
+ __FUNC_EXIT__;
+ return FALSE;
+ }
+
+ req->client_source_idle_id = 0;
+ printf("send_request [%s]\n", req->buf + 2);
+ size = htonl(req->used);
+ res = __write_sock(req->client_sock, (unsigned char *)&size, sizeof(size));
+ if (res != 0) {
+ printf("failed to send size with network byte order\n");
+ destroy_source_gio(req);
+ __FUNC_EXIT__;
+ return FALSE;
+ }
+
+ res = __write_sock(req->client_sock, req->buf, req->used);
+ if (res != 0) {
+ printf("failed to send pkt\n");
+ destroy_source_gio(req);
+ __FUNC_EXIT__;
+ return FALSE;
+ }
+
+ return FALSE;
+}
+
+static gboolean process_gio_source_sock(GIOChannel *source,
+ GIOCondition condition,
+ gpointer user_data)
+{
+ struct request *req = NULL;
+ unsigned int pkt_size = 0;
+ unsigned char *buf = NULL;
+ int sock = 0;
+ int res = 0;
+ __FUNC_ENTER__;
+
+ req = (struct request *)user_data;
+ if (!req) {
+ printf("Invalid parameter\n");
+ __FUNC_EXIT__;
+ return FALSE;
+ }
+
+ sock = g_io_channel_unix_get_fd(source);
+ if (sock < SOCK_FD_MIN) {
+ printf("Invalid argument\n");
+ __FUNC_EXIT__;
+ return FALSE;
+ }
+
+ if ((condition & G_IO_ERR) || (condition & G_IO_HUP) || (condition & G_IO_NVAL)) {
+ printf("G_IO_ERR/G_IO_HUP/G_IO_NVAL received sock [%d] condition [%d]\n", sock, condition);
+ req->client_source_idle_id = 0;
+ destroy_source_gio(req);
+ __FUNC_EXIT__;
+ return FALSE;
+ }
+#ifdef ENABLE_DEBUG_MODE_INFO
+ printf("condition [%d] sock [%d]\n",condition, sock);
+#endif
+ if (req->rcv_pkt_size == 0) {
+#ifdef ENABLE_DEBUG_MODE_INFO
+ printf("read packet size\n");
+#endif
+ if (__read_sock(sock, (unsigned char *)&pkt_size, sizeof(pkt_size)) < 0) {
+ printf("read packet size failed\n");
+ req->client_source_idle_id = 0;
+ destroy_source_gio(req);
+ __FUNC_EXIT__;
+ return FALSE;
+ }
+
+ req->rcv_pkt_size = ntohl(pkt_size);
+#ifdef ENABLE_DEBUG_MODE_INFO
+ printf("packet size [%u]\n", req->rcv_pkt_size);
+#endif
+ } else {
+ buf = g_try_malloc0(req->rcv_pkt_size);
+ if (buf == NULL) {
+ printf("Failed to allocate memory\n");
+ req->client_source_idle_id = 0;
+ destroy_source_gio(req);
+ __FUNC_EXIT__;
+ return FALSE;
+ }
+#ifdef ENABLE_DEBUG_MODE_INFO
+ printf("read packet\n");
+#endif
+ if (__read_sock(sock, buf, req->rcv_pkt_size) < 0) {
+ printf("read packet failed\n");
+ req->client_source_idle_id = 0;
+ destroy_source_gio(req);
+ g_free(buf);
+ __FUNC_EXIT__;
+ return FALSE;
+ }
+#ifdef ENABLE_DEBUG_MODE_INFO
+ printf("[%s]\n", req->buf + 2);
+#endif
+ req->handler(buf, req->rcv_pkt_size);
+ g_free(buf);
+ req->rcv_pkt_size = 0;
+ }
+ __FUNC_EXIT__;
+ return TRUE;
+}
+
+/* test load-conn */
+
+typedef void (*destroy_data)(void *data);
+
+typedef struct section {
+ char *id_str;
+ GHashTable *kv;
+ GHashTable *kvl;
+ void *data;
+ destroy_data destroy_func;
+} section_s;
+
+typedef struct conn {
+ GSList *locals;
+ GSList *remotes;
+ GSList *children;
+} conn_s;
+
+typedef enum
+{
+ EAP,
+ XAUTH,
+ IKE,
+ PRIVATE,
+ RSA,
+ ECDSA,
+ PKCS8,
+ PKCS12,
+} secret_type_e;
+
+typedef struct secret {
+ secret_type_e type;
+} secret_s;
+
+typedef struct setting {
+ GSList *conns;
+ GSList *secrets;
+ GSList *pools;
+ GSList *authorities;
+} setting_s;
+
+
+/* create swanctl.conf */
+/* add <conn> */
+/* add local */
+/* add remote */
+/* add children */
+/* add secrets */
+/* add pools */
+/* add authorities */
+
+static void __remove_list(gpointer data)
+{
+ GSList *list = NULL;
+ char *value = NULL;
+
+ if (data == NULL)
+ return;
+
+ g_slist_free_full(list, g_free);
+}
+
+section_s *get_section(GSList *list, const char *id_str)
+{
+ section_s *section = NULL;
+ __FUNC_ENTER__;
+
+ if (list == NULL)
+ return NULL;
+
+ for (; list; list = list->next) {
+ section = list->data;
+ if (section && g_strcmp0(id_str, section->id_str) == 0)
+ break;
+ section = NULL;
+ }
+
+ __FUNC_EXIT__;
+ return section;
+}
+
+section_s *add_section(GSList **list, const char *id_str)
+{
+ section_s *section = NULL;
+ int ret = 0;
+ __FUNC_ENTER__;
+
+ section = get_section(*list, id_str);
+ if (section)
+ return section;
+
+ section = g_try_malloc0(sizeof(section_s));
+ if (section == NULL)
+ return section;
+
+ section->id_str = g_strdup(id_str);
+ section->kv = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+ section->kvl = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, __remove_list);
+ *list = g_slist_prepend(*list, section);
+ printf("%s %d\n", id_str, g_slist_length(*list));
+ __FUNC_EXIT__;
+ return section;
+}
+
+void del_section(GSList *list, const char *id_str)
+{
+ section_s *section = NULL;
+ __FUNC_ENTER__;
+
+ section = get_section(list, id_str);
+ if (section == NULL)
+ return;
+
+ list = g_slist_remove(list, section);
+ g_hash_table_remove_all(section->kv);
+ g_hash_table_remove_all(section->kvl);
+ g_free(section->id_str);
+ if (section->destroy_func)
+ section->destroy_func(section->data);
+ g_free(section);
+
+ __FUNC_EXIT__;
+ return;
+}
+
+void add_section_kv(section_s *section, char *key, char *value)
+{
+ if (section == NULL || key == NULL || value == NULL)
+ return;
+ g_hash_table_insert(section->kv, g_strdup(key), g_strdup(value));
+ return;
+}
+
+void add_section_kvl(section_s *section, char *key, GSList *list)
+{
+ if (section == NULL || key == NULL || list == NULL)
+ return;
+
+ g_hash_table_insert(section->kvl, g_strdup(key), g_slist_copy(list));
+ return;
+}
+
+void add_section_kv_args(section_s *section, char *key, int num_args, ...)
+{
+ GSList *list = NULL;
+ va_list args_ptr;
+ char *temp = NULL;
+ int i = 0;
+ __FUNC_ENTER__;
+
+ if (section == NULL || key == NULL || num_args == 0)
+ return;
+
+ va_start(args_ptr, num_args);
+ for(i = 0; i < num_args; i++) {
+ temp = va_arg(args_ptr, char *);
+ list = g_slist_prepend(list, g_strdup(temp));
+ }
+
+ g_hash_table_insert(section->kvl, g_strdup(key), list);
+ __FUNC_EXIT__;
+ return;
+}
+
+/* write section into req */
+
+typedef void (*handle_data)(void *data, struct request *req);
+
+void write_section_kv(section_s *section, struct request *req)
+{
+ GHashTableIter iter;
+ gpointer key, value;
+ int ret = 0;
+ __FUNC_ENTER__;
+
+ if (section == NULL || req == NULL)
+ return;
+
+ g_hash_table_iter_init (&iter, section->kv);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ if (!key || !value)
+ continue;
+ vici_kv(req, (const char*)key, (const void *)value, strlen((char *)value));
+ }
+ __FUNC_EXIT__;
+ return;
+}
+
+static void __write_vl(gpointer data, gpointer user_data)
+{
+ struct request *req = NULL;
+ char *value = NULL;
+ __FUNC_ENTER__;
+
+ if (!data || !user_data)
+ return;
+
+ value = (char *)data;
+ req = (struct request *)user_data;
+ vici_list_item(req, value, strlen(value));
+
+ __FUNC_EXIT__;
+ return;
+}
+
+void write_section_kvl(section_s *section, struct request *req)
+{
+ GHashTableIter iter;
+ gpointer key, value;
+ int ret = 0;
+ __FUNC_ENTER__;
+
+ if (section == NULL || req == NULL)
+ return;
+
+ g_hash_table_iter_init (&iter, section->kvl);
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ if (!key || !value)
+ continue;
+
+ vici_list_start(req, key);
+ g_slist_foreach((GSList *)value, (GFunc)__write_vl, (gpointer)req);
+ vici_list_end(req);
+ }
+ __FUNC_EXIT__;
+ return;
+}
+
+void write_section(section_s *section, handle_data handler, struct request *req)
+{
+ if (section == NULL || req == NULL)
+ return;
+ vici_section_start(req, section->id_str);
+ write_section_kv(section, req);
+ if(handler)
+ handler(section->data, req);
+ vici_section_end(req);
+ return;
+}
+
+void write_section_list(GSList *list, handle_data handler, struct request *req)
+{
+ GSList *temp = NULL;
+ section_s *section = NULL;
+ __FUNC_ENTER__;
+
+ if(list == NULL || req == NULL)
+ return;
+
+ for (; list; list = list->next) {
+ section = list->data;
+ if (!section)
+ continue;
+
+ vici_section_start(req, section->id_str);
+ write_section_kv(section, req);
+ write_section_kvl(section, req);
+ if(handler)
+ handler(section->data, req);
+ vici_section_end(req);
+ }
+
+ __FUNC_EXIT__;
+ return;
+}
+
+void handle_conns(void *data, struct request *req)
+{
+ conn_s *conn = NULL;
+ __FUNC_ENTER__;
+
+ if (data == NULL || req == NULL)
+ return;
+
+ conn = (conn_s *)data;
+ write_section_list(conn->locals, NULL, req);
+ write_section_list(conn->remotes, NULL, req);
+ vici_section_start(req, "children");
+ write_section_list(conn->children, NULL, req);
+ vici_section_end(req);
+ __FUNC_EXIT__;
+ return;
+}
+
+static unsigned char *get_file(const char *file_path, unsigned long long *size)
+{
+ struct stat st;
+ FILE *fp = NULL;
+ int fd = 0;
+ unsigned long long file_size = 0;
+ unsigned char *file_buff = NULL;
+
+ if (!file_path) {
+ printf("Invalid file_path!\n");
+ return NULL;
+ }
+
+ fp = fopen(file_path, "rb");
+ if (!fp) {
+ printf("fopen for %s failed!\n", file_path);
+ return NULL;
+ }
+ fd = fileno(fp);
+ fstat(fd, &st);
+ file_size = st.st_size;
+ file_buff = g_try_malloc0(sizeof(char)*st.st_size);
+ if (file_buff == NULL) {
+ printf("g_try_malloc0 failed\n");
+ fclose(fp);
+ __FUNC_EXIT__;
+ return NULL;
+ }
+ fread(file_buff, 1, file_size, fp);
+ fclose(fp);
+ fp = NULL;
+ fd = 0;
+
+ *size = file_size;
+ return file_buff;
+}
+
+typedef conn_s *(*create_conn)(setting_s *setting);
+typedef void (*destroy_conn)(conn_s *conn);
+
+static conn_s * create_conn_for_hybrid(setting_s *setting);
+static conn_s * create_conn_for_xauth_psk(setting_s *setting);
+static conn_s * create_conn_for_xauth_rsa(setting_s *setting);
+static conn_s * create_conn_for_ikev2_psk(setting_s *setting);
+static conn_s * create_conn_for_ikev2_rsa(setting_s *setting);
+
+static void destroy_conn_for_hybrid(conn_s *conn);
+static void destroy_conn_for_xauth_psk(conn_s *conn);
+static void destroy_conn_for_xauth_rsa(conn_s *conn);
+static void destroy_conn_for_ikev2_psk(conn_s *conn);
+static void destroy_conn_for_ikev2_rsa(conn_s *conn);
+
+struct ipsec_type_id_value {
+ int id;
+ const char *head;
+ const char *conn_name;
+ const char *child_name;
+ const char *pool_name;
+ create_conn create;
+ destroy_conn destroy;
+} ipsec_info[] = {
+ {IPSEC_HYBRID_RSA, "IPsec Hybrid RSA",
+ "conn_hybrid", "child_hybrid", "pool_hybrid",
+ create_conn_for_hybrid, destroy_conn_for_hybrid},
+
+ {IPSEC_XAUTH_PSK, "IPsec Xauth PSK",
+ "conn_xauth_psk", "child_xauth_psk", "pool_xauth_psk",
+ create_conn_for_xauth_psk, destroy_conn_for_xauth_psk},
+
+ {IPSEC_XAUTH_RSA, "IPsec Xauth RSA",
+ "conn_xauth_rsa", "child_xauth_rsa", "pool_xauth_rsa",
+ create_conn_for_xauth_rsa, destroy_conn_for_xauth_rsa},
+
+ {IPSEC_IKEV2_PSK, "IPsec IKEv2 PSK",
+ "conn_ikev2_psk", "child_ikev2_psk", "pool_ikev2_psk",
+ create_conn_for_ikev2_psk, destroy_conn_for_ikev2_psk},
+
+ {IPSEC_IKEV2_RSA, "IPsec IKEv2 RSA",
+ "conn_ikev2_rsa", "child_ikev2_rsa", "pool_ikev2_rsa",
+ create_conn_for_ikev2_rsa, destroy_conn_for_ikev2_rsa},
+};
+
+static void add_default_conn_value(section_s *section)
+{
+ add_section_kv_args(section, "local_addrs", 1, strongswan_conf[LOCAL_IP].value);
+ add_section_kv_args(section, "remote_addrs", 1, "%any");
+
+ add_section_kv(section, "keyingtries", "1");
+ add_section_kv(section, "reauth_time", "0");
+ add_section_kv(section, "rekey_time", "4h");
+
+ return;
+}
+
+static void add_default_child_value(section_s *section)
+{
+ add_section_kv_args(section, "local_ts", 1, strongswan_conf[LOCAL_TS].value);
+ add_section_kv(section, "start_action", "none");
+ add_section_kv(section, "updown", "/usr/local/libexec/ipsec/_updown iptables");
+ add_section_kv(section, "rekey_time", "10m");
+
+ return;
+}
+
+static void add_proposals_for_ikev1(section_s *section)
+{
+ GSList *list = NULL;
+ list = g_slist_append(list, g_strdup("aes256-sha256-modp1024"));
+ list = g_slist_append(list, g_strdup("aes128-sha256-modp1024"));
+ list = g_slist_append(list, g_strdup("aes256-sha1-modp1024"));
+ list = g_slist_append(list, g_strdup("aes128-sha1-modp1024"));
+ list = g_slist_append(list, g_strdup("aes256-md5-modp1024"));
+ list = g_slist_append(list, g_strdup("aes128-md5-modp1024"));
+ list = g_slist_append(list, g_strdup("3des-sha1-modp1024"));
+ list = g_slist_append(list, g_strdup("3des-md5-modp1024"));
+ add_section_kvl(section, "proposals", list);
+ list = NULL;
+
+ return;
+}
+
+static void add_esp_proposals_for_ikev1(section_s *section)
+{
+ GSList *list = NULL;
+ list = g_slist_append(list, g_strdup("aes256-sha256"));
+ list = g_slist_append(list, g_strdup("aes128-sha256"));
+ list = g_slist_append(list, g_strdup("aes256-sha1"));
+ list = g_slist_append(list, g_strdup("aes128-sha1"));
+ list = g_slist_append(list, g_strdup("aes256-md5"));
+ list = g_slist_append(list, g_strdup("aes128-md5"));
+ list = g_slist_append(list, g_strdup("3des-sha1"));
+ list = g_slist_append(list, g_strdup("3des-md5"));
+ add_section_kvl(section, "esp_proposals", list);
+ list = NULL;
+
+ return;
+}
+
+static void add_proposals_for_ikev2(section_s *section)
+{
+ GSList *list = NULL;
+ list = g_slist_append(list, g_strdup("aes256-aes128-sha512-sha384-sha256-sha1-modp2048s256-ecp384-ecp256-modp2048-modp1536-modp1024"));
+ //list = g_slist_append(list, g_strdup("aes256gcm16-aes128gcm16-prfsha512-prfsha384-prfsha256-prfsha1-modp2048s256-ecp384-ecp256-modp2048-modp1536-modp1024"));
+ add_section_kvl(section, "proposals", list);
+ list = NULL;
+
+ return;
+}
+
+static void add_esp_proposals_for_ikev2(section_s *section)
+{
+ GSList *list = NULL;
+ list = g_slist_append(list, g_strdup("aes256-aes128-sha512-sha384-sha256-sha1"));
+ //list = g_slist_append(list, g_strdup("aes256gcm16-aes128gcm16-prfsha512-prfsha384-prfsha256-prfsha1-modp2048s256-ecp384-ecp256-modp2048-modp1536-modp1024"));
+ add_section_kvl(section, "esp_proposals", list);
+ list = NULL;
+
+ return;
+}
+
+static void add_auth_for_hybrid(conn_s *conn)
+{
+ section_s *section = NULL;
+ unsigned char *file_buff;
+ unsigned long long file_size = 0;
+
+ /* add local */
+ section = add_section(&(conn->locals), "local");
+ section->destroy_func = NULL;
+
+ add_section_kv(section, "auth", "pubkey");
+ add_section_kv(section, "id", strongswan_conf[LOCAL_IP].value);
+
+ file_buff = get_file(strongswan_conf[CERT_PATH].value, &file_size);
+ if (file_buff)
+ add_section_kv_args(section, "certs", 1, file_buff);
+
+ /* add remote */
+
+ section = add_section(&(conn->remotes), "remote");
+ section->destroy_func = NULL;
+
+ add_section_kv(section, "auth", "xauth");
+
+ return;
+}
+
+static void add_auth_for_xauth_psk(conn_s *conn)
+{
+ section_s *section = NULL;
+
+ /* add local */
+ section = add_section(&(conn->locals), "local");
+ section->destroy_func = NULL;
+
+ add_section_kv(section, "auth", "psk");
+
+ /* add remote-xauth */
+ section = add_section(&(conn->remotes), "remote-xauth");
+ section->destroy_func = NULL;
+
+ add_section_kv(section, "auth", "xauth");
+
+ /* add remote */
+
+ section = add_section(&(conn->remotes), "remote");
+ section->destroy_func = NULL;
+
+ add_section_kv(section, "auth", "psk");
+
+ return;
+}
+
+static void add_auth_for_xauth_rsa(conn_s *conn)
+{
+ section_s *section = NULL;
+ unsigned char *file_buff;
+ unsigned long long file_size = 0;
+
+ /* add local */
+ section = add_section(&(conn->locals), "local");
+ section->destroy_func = NULL;
+
+ add_section_kv(section, "auth", "pubkey");
+ add_section_kv(section, "id", strongswan_conf[LOCAL_IP].value);
+
+ file_buff = get_file(strongswan_conf[CERT_PATH].value, &file_size);
+ if (file_buff)
+ add_section_kv_args(section, "certs", 1, file_buff);
+
+ /* add remote-xauth */
+ section = add_section(&(conn->remotes), "remote-xauth");
+ section->destroy_func = NULL;
+
+ add_section_kv(section, "auth", "xauth");
+
+ /* add remote */
+
+ section = add_section(&(conn->remotes), "remote");
+ section->destroy_func = NULL;
+
+ add_section_kv(section, "auth", "pubkey");
+
+ return;
+}
+
+static void add_auth_for_ikev2_psk(conn_s *conn)
+{
+ section_s *section = NULL;
+
+ /* add local */
+ section = add_section(&(conn->locals), "local");
+ section->destroy_func = NULL;
+
+ add_section_kv(section, "auth", "psk");
+
+ /* add remote */
+
+ section = add_section(&(conn->remotes), "remote");
+ section->destroy_func = NULL;
+
+ add_section_kv(section, "auth", "psk");
+
+ return;
+}
+
+static void add_auth_for_ikev2_rsa(conn_s *conn)
+{
+ section_s *section = NULL;
+ unsigned char *file_buff;
+ unsigned long long file_size = 0;
+
+ /* add local */
+ section = add_section(&(conn->locals), "local");
+ section->destroy_func = NULL;
+
+ add_section_kv(section, "auth", "pubkey");
+ add_section_kv(section, "id", strongswan_conf[LOCAL_IP].value);
+
+ file_buff = get_file(strongswan_conf[CERT_PATH].value, &file_size);
+ if (file_buff)
+ add_section_kv_args(section, "certs", 1, file_buff);
+
+ /* add remote */
+
+ section = add_section(&(conn->remotes), "remote");
+ section->destroy_func = NULL;
+
+ add_section_kv(section, "auth", "pubkey");
+
+ return;
+}
+
+static void create_child_for_hybrid(conn_s *conn)
+{
+ section_s *section = NULL;
+
+ section = add_section(&(conn->children),
+ ipsec_info[IPSEC_HYBRID_RSA].child_name);
+ /* TODO: handle memory fault */
+ section->destroy_func = NULL;
+
+ add_default_child_value(section);
+ add_esp_proposals_for_ikev1(section);
+
+ return;
+}
+
+static conn_s *create_conn_for_hybrid(setting_s *setting)
+{
+ section_s *section = NULL;
+ conn_s *conn = NULL;
+
+ /* add <conn> */
+ section = add_section(&(setting->conns),
+ ipsec_info[IPSEC_HYBRID_RSA].conn_name);
+ /* TODO: handle memory fault */
+
+ conn = g_try_malloc0(sizeof(conn_s));
+ /* TODO: handle memory fault */
+ section->data = conn;
+ section->destroy_func = g_free;
+
+ add_section_kv_args(section, "pools", 1,
+ ipsec_info[IPSEC_HYBRID_RSA].pool_name);
+ add_section_kv(section, "version", "1");
+ add_section_kv(section, "send_cert", "always");
+
+ add_default_conn_value(section);
+ add_proposals_for_ikev1(section);
+
+ add_auth_for_hybrid(conn);
+ create_child_for_hybrid(conn);
+
+ return conn;
+}
+
+static void destroy_conn_for_hybrid(conn_s *conn)
+{
+ del_section(conn->children, ipsec_info[IPSEC_HYBRID_RSA].child_name);
+ del_section(conn->locals, "local");
+ del_section(conn->remotes, "remote");
+
+ return;
+}
+
+static void create_child_for_xauth_psk(conn_s *conn)
+{
+ section_s *section = NULL;
+
+ section = add_section(&(conn->children), ipsec_info[IPSEC_XAUTH_PSK].child_name);
+ section->destroy_func = NULL;
+
+ add_default_child_value(section);
+ add_esp_proposals_for_ikev1(section);
+
+ return;
+}
+
+static conn_s *create_conn_for_xauth_psk(setting_s *setting)
+{
+ section_s *section = NULL;
+ conn_s *conn = NULL;
+
+ /* add <conn> */
+ section = add_section(&(setting->conns),
+ ipsec_info[IPSEC_XAUTH_PSK].conn_name);
+ /* TODO: handle memory fault */
+
+ conn = g_try_malloc0(sizeof(conn_s));
+ /* TODO: handle memory fault */
+ section->data = conn;
+ section->destroy_func = g_free;
+
+ add_section_kv_args(section, "pools", 1,
+ ipsec_info[IPSEC_XAUTH_PSK].pool_name);
+
+ add_section_kv(section, "version", "1");
+ add_section_kv(section, "send_certreq", "no");
+ add_section_kv(section, "aggressive", "yes");
+
+ add_default_conn_value(section);
+ add_proposals_for_ikev1(section);
+
+ add_auth_for_xauth_psk(conn);
+ create_child_for_xauth_psk(conn);
+
+ return conn;
+}
+
+static void destroy_conn_for_xauth_psk(conn_s *conn)
+{
+ del_section(conn->children, ipsec_info[IPSEC_XAUTH_PSK].child_name);
+ del_section(conn->locals, "local");
+ del_section(conn->remotes, "remote");
+ del_section(conn->remotes, "remote-xauth");
+
+}
+
+static void create_child_for_xauth_rsa(conn_s *conn)
+{
+ section_s *section = NULL;
+
+ /* add children */
+ section = add_section(&(conn->children),
+ ipsec_info[IPSEC_XAUTH_RSA].child_name);
+ /* TODO: handle memory fault */
+ section->destroy_func = NULL;
+
+ add_default_child_value(section);
+ add_esp_proposals_for_ikev1(section);
+
+ return;
+}
+
+static conn_s *create_conn_for_xauth_rsa(setting_s *setting)
+{
+ section_s *section = NULL;
+ conn_s *conn = NULL;
+
+ /* add <conn> */
+ section = add_section(&(setting->conns),
+ ipsec_info[IPSEC_XAUTH_RSA].conn_name);
+ /* TODO: handle memory fault */
+
+ conn = g_try_malloc0(sizeof(conn_s));
+ /* TODO: handle memory fault */
+ section->data = conn;
+ section->destroy_func = g_free;
+
+ add_section_kv_args(section, "pools", 1,
+ ipsec_info[IPSEC_XAUTH_RSA].pool_name);
+ add_section_kv(section, "version", "1");
+
+ add_default_conn_value(section);
+ add_proposals_for_ikev1(section);
+
+ add_auth_for_xauth_rsa(conn);
+ create_child_for_xauth_rsa(conn);
+
+ return conn;
+}
+
+static void destroy_conn_for_xauth_rsa(conn_s *conn)
+{
+ del_section(conn->children, ipsec_info[IPSEC_XAUTH_RSA].child_name);
+ del_section(conn->locals, "local");
+ del_section(conn->remotes, "remote");
+ del_section(conn->remotes, "remote-xauth");
+ return;
+}
+
+
+static void create_child_for_ikev2_psk(conn_s *conn)
+{
+ section_s *section = NULL;
+
+ section = add_section(&(conn->children),
+ ipsec_info[IPSEC_IKEV2_PSK].child_name);
+ /* TODO: handle memory fault */
+ section->destroy_func = NULL;
+
+ add_default_child_value(section);
+ add_esp_proposals_for_ikev2(section);
+
+ return;
+}
+
+static conn_s *create_conn_for_ikev2_psk(setting_s *setting)
+{
+ section_s *section = NULL;
+ conn_s *conn = NULL;
+
+ /* add <conn> */
+ section = add_section(&(setting->conns),
+ ipsec_info[IPSEC_IKEV2_PSK].conn_name);
+ /* TODO: handle memory fault */
+
+ conn = g_try_malloc0(sizeof(conn_s));
+ /* TODO: handle memory fault */
+ section->data = conn;
+ section->destroy_func = g_free;
+
+ add_section_kv_args(section, "pools", 1,
+ ipsec_info[IPSEC_IKEV2_PSK].pool_name);
+ add_section_kv(section, "version", "2");
+ add_section_kv(section, "send_certreq", "no");
+
+ add_default_conn_value(section);
+ add_proposals_for_ikev2(section);
+
+ add_auth_for_ikev2_psk(conn);
+ create_child_for_ikev2_psk(conn);
+
+ return conn;
+}
+
+static void destroy_conn_for_ikev2_psk(conn_s *conn)
+{
+ del_section(conn->children, ipsec_info[IPSEC_IKEV2_PSK].child_name);
+ del_section(conn->locals, "local");
+ del_section(conn->remotes, "remote");
+
+ return;
+}
+
+static void create_child_for_ikev2_rsa(conn_s *conn)
+{
+ section_s *section = NULL;
+
+ /* add children */
+
+ section = add_section(&(conn->children),
+ ipsec_info[IPSEC_IKEV2_RSA].child_name);
+ /* TODO: handle memory fault */
+ section->destroy_func = NULL;
+
+ add_default_child_value(section);
+ add_esp_proposals_for_ikev2(section);
+
+ return;
+}
+
+static conn_s *create_conn_for_ikev2_rsa(setting_s *setting)
+{
+ section_s *section = NULL;
+ conn_s *conn = NULL;
+
+ /* add <conn> */
+ section = add_section(&(setting->conns),
+ ipsec_info[IPSEC_IKEV2_RSA].conn_name);
+ /* TODO: handle memory fault */
+
+ conn = g_try_malloc0(sizeof(conn_s));
+ /* TODO: handle memory fault */
+ section->data = conn;
+ section->destroy_func = g_free;
+
+ add_section_kv_args(section, "pools", 1,
+ ipsec_info[IPSEC_IKEV2_RSA].pool_name);
+ add_section_kv(section, "version", "2");
+
+ add_default_conn_value(section);
+ add_proposals_for_ikev2(section);
+
+ add_auth_for_ikev2_rsa(conn);
+ create_child_for_ikev2_rsa(conn);
+
+ return conn;
+}
+
+static void destroy_conn_for_ikev2_rsa(conn_s *conn)
+{
+ del_section(conn->children, ipsec_info[IPSEC_IKEV2_RSA].child_name);
+ del_section(conn->locals, "local");
+ del_section(conn->remotes, "remote");
+
+ return;
+}
+
+static int send_vici_request(struct request *req)
+{
+ int res =
+ send_request_gio((GIOFunc)process_gio_source_sock,
+ (GSourceFunc)send_request_gio_in_idle,
+ (GSourceFunc)destroy_source_gio,
+ (gpointer)req);
+ return res;
+}
+
+static void check_vici_request(struct request *req)
+{
+ __process_response(req->buf + req->hdr_len - 1, req->used - req->hdr_len + 1);
+}
+
+static int test_load_conn(int ipsec_type)
+{
+ setting_s *setting = NULL;
+ section_s *section = NULL;
+ conn_s * conn = NULL;
+ struct request *req = NULL;
+ int ret = 0;
+ __FUNC_ENTER__;
+
+ printf("load-conn ipsec type [%s]\n", ipsec_info[ipsec_type].head);
+
+ ret = create_request(VICI_CMD_REQUEST, "load-conn", &req);
+ if (ret < 0) {
+ printf("error on create_request\n");
+ return -1;
+ }
+
+ setting = g_try_malloc0(sizeof(setting_s));
+ if (setting == NULL) {
+ printf("error on memory\n");
+ destroy_request(req);
+ return -1;
+ }
+
+ conn = ipsec_info[ipsec_type].create(setting);
+ if (conn == NULL) {
+ printf("error on memory\n");
+ destroy_request(req);
+ g_free(setting);
+ return -1;
+ }
+
+ /* create request for load-conn with setting */
+ write_section_list(setting->conns, handle_conns, req);
+
+ /* clear setting */
+ ipsec_info[ipsec_type].destroy(conn);
+ del_section(setting->conns, ipsec_info[ipsec_type].conn_name);
+ g_free(setting);
+
+/* send request */
+ check_vici_request(req);
+ send_vici_request(req);
+ if (ret < 0) {
+ printf("error on send_vici_request\n");
+ destroy_request(req);
+ }
+
+ __FUNC_EXIT__;
+ return ret;
+}
+
+int test_unload_conn(int ipsec_type)
+{
+ struct request *req = NULL;
+ int ret = 0;
+ __FUNC_ENTER__;
+
+ printf("unload-conn ipsec type [%s]\n", ipsec_info[ipsec_type].head);
+
+ ret = create_request(VICI_CMD_REQUEST, "unload-conn", &req);
+ if (ret < 0) {
+ printf("error on create_request\n");
+ return -1;
+ }
+
+ vici_kv(req, "name", (const void *)ipsec_info[ipsec_type].conn_name,
+ strlen((char *)ipsec_info[ipsec_type].conn_name));
+
+ check_vici_request(req);
+ send_vici_request(req);
+ if (ret < 0) {
+ printf("error on send_vici_request\n");
+ destroy_request(req);
+ }
+
+ __FUNC_EXIT__;
+ return ret;
+}
+
+int test_get_conns()
+{
+ struct request *req = NULL;
+ int ret = 0;
+ __FUNC_ENTER__;
+
+ ret = create_request(VICI_CMD_REQUEST, "get-conns", &req);
+ if (ret < 0) {
+ printf("error on create_request\n");
+ return -1;
+ }
+
+ check_vici_request(req);
+ send_vici_request(req);
+ if (ret < 0) {
+ printf("error on send_vici_request\n");
+ destroy_request(req);
+ }
+
+ __FUNC_EXIT__;
+ return ret;
+}
+
+int test_list_conns(int ipsec_type)
+{
+ struct request *req = NULL;
+ int ret = 0;
+ __FUNC_ENTER__;
+
+ printf("list-conn ipsec type [%s]\n", ipsec_info[ipsec_type].head);
+
+ ret = create_request(VICI_CMD_REQUEST, "list-conns", &req);
+ if (ret < 0) {
+ printf("error on create_request\n");
+ return -1;
+ }
+
+ vici_list_start(req, (const char *)"ike");
+ vici_list_item(req, (const void *)ipsec_info[ipsec_type].conn_name,
+ strlen((char *)ipsec_info[ipsec_type].conn_name));
+ vici_list_end(req);
+
+ check_vici_request(req);
+ send_vici_request(req);
+ if (ret < 0) {
+ printf("error on send_vici_request\n");
+ destroy_request(req);
+ }
+
+ __FUNC_EXIT__;
+ return ret;
+}
+
+/* test initiate */
+
+int test_initiate()
+{
+ struct request *req = NULL;
+ int ret = 0;
+ __FUNC_ENTER__;
+/*
+ ret = create_request(VICI_CMD_REQUEST, "initiate", &req);
+ if (ret < 0) {
+ printf("error on create_request\n");
+ return -1;
+ }
+
+ vici_kv(req, "child", (const void *)CHILD_SA_NAME, strlen((char *)CHILD_SA_NAME));
+
+ check_vici_request(req);
+ send_vici_request(req);
+*/
+ __FUNC_EXIT__;
+ return ret;
+}
+
+/* test terminate */
+
+int test_terminate(int ipsec_type)
+{
+ struct request *req = NULL;
+ int ret = 0;
+ __FUNC_ENTER__;
+
+ printf("terminate ipsec type [%s]\n", ipsec_info[ipsec_type].head);
+
+ ret = create_request(VICI_CMD_REQUEST, "terminate", &req);
+ if (ret < 0) {
+ printf("error on create_request\n");
+ return -1;
+ }
+
+ vici_kv(req, "child", (const void *)ipsec_info[ipsec_type].child_name,
+ strlen((char *)ipsec_info[ipsec_type].child_name));
+
+ check_vici_request(req);
+ send_vici_request(req);
+ if (ret < 0) {
+ printf("error on send_vici_request\n");
+ destroy_request(req);
+ }
+
+ __FUNC_EXIT__;
+ return ret;
+}
+
+int test_load_shared_psk()
+{
+ struct request *req = NULL;
+ int ret = 0;
+ __FUNC_ENTER__;
+
+ ret = create_request(VICI_CMD_REQUEST, "load-shared", &req);
+ if (ret < 0) {
+ printf("error on create_request\n");
+ return -1;
+ }
+
+ vici_kv(req, "type", (const void *)"ike", strlen((char *)"ike"));
+ vici_kv(req, "data", (const void *)strongswan_conf[IKE_DATA].value,
+ strlen((char *)strongswan_conf[IKE_DATA].value));
+
+ vici_list_start(req, (const char *)"owners");
+ vici_list_item(req, (const void *)strongswan_conf[IKE_OWNER].value,
+ strlen((char *)strongswan_conf[IKE_OWNER].value));
+
+ vici_list_end(req);
+
+ check_vici_request(req);
+ send_vici_request(req);
+ if (ret < 0) {
+ printf("error on send_vici_request\n");
+ destroy_request(req);
+ }
+
+ __FUNC_EXIT__;
+ return ret;
+}
+
+int test_load_shared_xauth()
+{
+ struct request *req = NULL;
+ int ret = 0;
+ __FUNC_ENTER__;
+
+ ret = create_request(VICI_CMD_REQUEST, "load-shared", &req);
+ if (ret < 0) {
+ printf("error on create_request\n");
+ return -1;
+ }
+
+ vici_kv(req, "type", (const void *)"xauth", strlen((char *)"xauth"));
+ vici_kv(req, "data", (const void *)strongswan_conf[XAUTH_DATA].value,
+ strlen((char *)strongswan_conf[XAUTH_DATA].value));
+
+ vici_list_start(req, (const char *)"owners");
+ vici_list_item(req, (const void *)strongswan_conf[XAUTH_OWNER].value,
+ strlen((char *)strongswan_conf[XAUTH_OWNER].value));
+
+ vici_list_end(req);
+
+ check_vici_request(req);
+ send_vici_request(req);
+ if (ret < 0) {
+ printf("error on send_vici_request\n");
+ destroy_request(req);
+ }
+
+ __FUNC_EXIT__;
+ return ret;
+}
+
+int test_load_pool(int ipsec_type)
+{
+ GSList *list = NULL;
+ section_s *section = NULL;
+ conn_s * conn = NULL;
+ struct request *req = NULL;
+ int ret = 0;
+ __FUNC_ENTER__;
+
+ printf("load-pool ipsec type [%s]\n", ipsec_info[ipsec_type].head);
+
+ ret = create_request(VICI_CMD_REQUEST, "load-pool", &req);
+ if (ret < 0) {
+ printf("error on create_request\n");
+ return -1;
+ }
+
+/* add <conn> */
+ section = add_section(&(list), ipsec_info[ipsec_type].pool_name);
+ /* TODO: handle memory fault */
+
+ add_section_kv(section, "addrs", strongswan_conf[HYBRID_POOL + ipsec_type].value);
+
+/* create request for load-pool with list */
+
+ write_section_list(list, NULL, req);
+
+/* clear setting */
+ del_section(list, ipsec_info[ipsec_type].pool_name);
+
+ check_vici_request(req);
+ send_vici_request(req);
+ if (ret < 0) {
+ printf("error on send_vici_request\n");
+ destroy_request(req);
+ }
+
+ __FUNC_EXIT__;
+ return ret;
+}
+
+int test_load_ca_cert()
+{
+ struct request *req = NULL;
+ unsigned char *file_buff = NULL;
+ unsigned long long file_size = 0;
+ int ret = 0;
+ __FUNC_ENTER__;
+
+ file_buff = get_file(strongswan_conf[CA_CERT_PATH].value, &file_size);
+ if (!file_buff) {
+ return -1;
+ }
+
+ ret = create_request(VICI_CMD_REQUEST, "load-cert", &req);
+ if (ret < 0) {
+ printf("error on create_request\n");
+ g_free(file_buff);
+ return -1;
+ }
+
+ vici_kv(req, "type", (const void *)"X509", strlen((char *)"X509"));
+ vici_kv(req, "type", (const void *)"flag", strlen((char *)"CA"));
+ vici_kv(req, "data", (const void *)file_buff, file_size);
+
+ check_vici_request(req);
+ send_vici_request(req);
+ if (ret < 0) {
+ printf("error on send_vici_request\n");
+ destroy_request(req);
+ }
+ g_free(file_buff);
+
+ __FUNC_EXIT__;
+ return ret;
+}
+
+int test_load_private()
+{
+ struct request *req = NULL;
+ unsigned char *file_buff = NULL;
+ unsigned long long file_size = 0;
+ int ret = 0;
+ __FUNC_ENTER__;
+
+ file_buff = get_file(strongswan_conf[PRIVATE_PATH].value, &file_size);
+ if (!file_buff) {
+ return -1;
+ }
+
+ ret = create_request(VICI_CMD_REQUEST, "load-key", &req);
+ if (ret < 0) {
+ printf("error on create_request\n");
+ g_free(file_buff);
+ return -1;
+ }
+
+ vici_kv(req, "type", (const void *)"RSA", strlen((char *)"RSA"));
+ vici_kv(req, "data", (const void *)file_buff, file_size);
+
+ check_vici_request(req);
+ send_vici_request(req);
+ ret = send_vici_request(req);
+ if (ret < 0) {
+ printf("error on send_vici_request\n");
+ destroy_request(req);
+ }
+
+ g_free(file_buff);
+
+ __FUNC_EXIT__;
+ return ret;
+}
+
+/* test version */
+
+int test_version()
+{
+ struct request *req = NULL;
+ int ret = 0;
+ __FUNC_ENTER__;
+
+ ret = create_request(VICI_CMD_REQUEST, "version", &req);
+ if (ret < 0) {
+ printf("error on create_request\n");
+ return -1;
+ }
+
+ check_vici_request(req);
+ ret = send_vici_request(req);
+ if (ret < 0) {
+ printf("error on send_vici_request\n");
+ destroy_request(req);
+ return -1;
+ }
+
+ __FUNC_EXIT__;
+ return ret;
+}
+
+enum {
+ CMD_QUIT,
+ CMD_FULL_MENU,
+ CMD_VERSION,
+ CMD_LOAD_CONN,
+ CMD_UNLOAD_CONN,
+ CMD_GET_CONNS,
+ CMD_LIST_CONNS,
+ CMD_LOAD_SHARED_PSK,
+ CMD_LOAD_SHARED_XAUTH,
+ CMD_LOAD_POOL,
+ CMD_LOAD_CA_CERT,
+ CMD_LOAD_PRIVATE,
+ CMD_INITIATE,
+ CMD_TERMINATE,
+
+ CMD_INVALID,
+};
+
+typedef struct {
+ int cmd;
+ char* menu_str;
+} menu_str_t;
+
+menu_str_t g_menu_str[] = {
+ { CMD_QUIT, "CMD_QUIT" },
+ { CMD_FULL_MENU, "CMD_FULL_MENU" },
+ { CMD_VERSION, "CMD_VERSION" },
+ { CMD_LOAD_CONN, "CMD_LOAD_CONN" },
+ { CMD_UNLOAD_CONN, "CMD_UNLOAD_CONN" },
+ { CMD_GET_CONNS, "CMD_GET_CONNS" },
+ { CMD_LIST_CONNS, "CMD_LIST_CONNS" },
+ { CMD_LOAD_SHARED_PSK, "CMD_LOAD_SHARED_PSK" },
+ { CMD_LOAD_SHARED_XAUTH, "CMD_LOAD_SHARED_XAUTH" },
+ { CMD_LOAD_POOL, "CMD_LOAD_POOL" },
+ { CMD_LOAD_CA_CERT, "CMD_LOAD_CA_CERT" },
+ { CMD_LOAD_PRIVATE, "CMD_LOAD_PRIVATE" },
+ { CMD_INITIATE, "CMD_INITIATE" },
+ { CMD_TERMINATE, "CMD_TERMINATE" },
+ { -1, NULL }, };
+
+void usage()
+{
+ printf("Call Test Program\n");
+ printf(" %d: quit\n", CMD_QUIT);
+ printf(" %d: Full menu\n", CMD_FULL_MENU);
+}
+
+char*
+cmd_transform(char*str)
+{
+ int i, j;
+ int len;
+ static char static_buffer[255];
+
+ if (str == NULL)
+ return "";
+
+ len = strlen(str);
+ if (len == 0)
+ return "";
+
+ /* remove "CMD_" */
+ /* lower char */
+ /* replance "_" to space */
+ for (i = 0, j = 4; i < len; i++, j++) {
+ if (str[j] >= 'A' && str[j] <= 'Z')
+ static_buffer[i] = str[j] + 'a' - 'A';
+ else if (str[j] == '_')
+ static_buffer[i] = ' ';
+ else
+ static_buffer[i] = str[j];
+ }
+ static_buffer[j] = '\0';
+
+ return static_buffer;
+}
+
+void usage_full()
+{
+ int i;
+ printf("Call Test Program\n");
+
+ for (i = 0; g_menu_str[i].cmd != -1; i++) {
+ if (i % 4 == 0)
+ printf("\n");
+ printf(" %02d: %-32s ", g_menu_str[i].cmd,
+ cmd_transform(g_menu_str[i].menu_str));
+
+ }
+ printf("\n");
+}
+
+int is_digit(const char* str)
+{
+ int len;
+ int i;
+
+ if (str == NULL)
+ return -1;
+
+ if (strlen(str) == 0)
+ return -1;
+
+ len = strlen(str);
+ for (i = 0; i < len; i++) {
+ if (str[i] < '0' || str[i] > '9')
+ return -2;
+ }
+
+ return 0;
+}
+
+void print_result(int cmd, int ret)
+{
+ if (ret != 0)
+ printf(MAKE_RED"%s failed\n", g_menu_str[cmd].menu_str);
+ else
+ printf(MAKE_GREEN"%s succeeded\n", g_menu_str[cmd].menu_str);
+ printf(RESET_COLOR);
+
+}
+
+int get_ipsec_type(int cmd)
+{
+ int type = IPSEC_HYBRID_RSA;
+ int i = 0;
+ printf("Please enter #of ipsec type for [%s]:\n", g_menu_str[cmd].menu_str);
+
+ for (type = IPSEC_HYBRID_RSA; type <= IPSEC_IKEV2_RSA; type++)
+ printf("[%d] : [%s]\n", type, ipsec_type_str[type].type_str);
+ scanf("%d", &type);
+
+ if (type < IPSEC_HYBRID_RSA || type > IPSEC_IKEV2_RSA)
+ type = -1;
+ return type;
+
+}
+
+
+void process_std_input(const char *input, gpointer user_data)
+{
+ int ret = -1;
+ int cmd = strtol(input, NULL, 0);
+
+ if (is_digit(input) < 0 || strlen(input) == 0 || errno == ERANGE || errno
+ == EINVAL)
+ cmd = CMD_INVALID;
+
+ printf("cmd=[%d]\n", cmd);
+
+ switch (cmd) {
+ case CMD_FULL_MENU:
+ {
+ usage_full();
+ }
+ break;
+ case CMD_QUIT:
+ {
+ printf("Bye\n");
+ g_main_loop_quit(main_loop);
+ }
+ break;
+ case CMD_VERSION:
+ {
+ ret = test_version();
+ print_result(cmd, ret);
+ }
+ break;
+ case CMD_LOAD_CONN:
+ {
+ int type;
+ type = get_ipsec_type(cmd);
+ if (type < 0)
+ break;
+ ret = test_load_conn(type);
+ print_result(cmd, ret);
+ }
+ break;
+ case CMD_UNLOAD_CONN:
+ {
+ int type;
+ type = get_ipsec_type(cmd);
+ if (type < 0)
+ break;
+ ret = test_unload_conn(type);
+ print_result(cmd, ret);
+ }
+ break;
+ case CMD_GET_CONNS:
+ {
+ ret = test_get_conns();
+ print_result(cmd, ret);
+ }
+ break;
+ case CMD_LIST_CONNS:
+ {
+ int type;
+ type = get_ipsec_type(cmd);
+ if (type < 0)
+ break;
+ ret = test_list_conns(type);
+ print_result(cmd, ret);
+ }
+ break;
+ case CMD_LOAD_SHARED_PSK:
+ {
+ ret = test_load_shared_psk();
+ print_result(cmd, ret);
+ }
+ break;
+ case CMD_LOAD_SHARED_XAUTH:
+ {
+ ret = test_load_shared_xauth();
+ print_result(cmd, ret);
+ }
+ break;
+ case CMD_LOAD_POOL:
+ {
+ int type;
+ type = get_ipsec_type(cmd);
+ if (type < 0)
+ break;
+ ret = test_load_pool(type);
+ print_result(cmd, ret);
+ }
+ break;
+ case CMD_LOAD_CA_CERT:
+ {
+ ret = test_load_ca_cert();
+ print_result(cmd, ret);
+ }
+ break;
+ case CMD_LOAD_PRIVATE:
+ {
+ ret = test_load_private();
+ print_result(cmd, ret);
+ }
+ break;
+ case CMD_INITIATE:
+ {
+ ret = test_initiate();
+ print_result(cmd, ret);
+ }
+ break;
+ case CMD_TERMINATE:
+ {
+ int type;
+ type = get_ipsec_type(cmd);
+ if (type < 0)
+ break;
+ ret = test_terminate(type);
+ print_result(cmd, ret);
+ }
+ break;
+ default:
+ usage_full();
+ break;
+ }
+
+ return;
+}
+
+static gboolean read_std_input(GIOChannel * source,
+ GIOCondition condition, gpointer user_data)
+{
+ int fd = 0;
+
+ static char buf[MAX_STD_INPUT_BUF];
+ int n;
+
+ errno = 0;
+ n = read(fd, buf, MAX_STD_INPUT_BUF);
+
+ buf[n - 1] = '\0'; /* remove new line... */
+ if (n == 0) {
+ printf("Error: read() from stdin returns 0.\n");
+ } else if (n < 0) {
+ printf("input: read, err=%s\n", strerror(errno));
+ } else {
+ printf("\n\n");
+ }
+
+ process_std_input(buf, user_data);
+
+ return TRUE;
+}
+
+static GKeyFile *load_key_file(const char *path_name)
+{
+ GKeyFile *key_file = NULL;
+ GError *error = NULL;
+
+ key_file = g_key_file_new();
+ if (!g_key_file_load_from_file(key_file, path_name, 0, &error)) {
+ printf("Unable to load %s: %s", path_name, error->message);
+ g_clear_error(&error);
+
+ g_key_file_free(key_file);
+ key_file = NULL;
+ }
+ return key_file;
+}
+
+int load_strongswan_config(const char *path_name)
+{
+ GKeyFile *key_file = NULL;
+ int i = 0;
+
+ key_file = load_key_file(path_name);
+ if (!key_file)
+ return -1;
+
+ for (i = LOCAL_IP; i < STRONGSWAN_CONF_KEY_MAX; i++) {
+ strongswan_conf[i].value = g_key_file_get_string(key_file, CONF_GROUP_NAME,
+ strongswan_conf[i].key_name, NULL);
+
+ if (strlen(strongswan_conf[i].value) == 0)
+ strongswan_conf[i].value = NULL;
+
+ printf ("key [%s] value [%s]\n",
+ strongswan_conf[i].key_name, strongswan_conf[i].value);
+ }
+
+ g_conf_key_file = key_file;
+ return 0;
+}
+
+void unload_strongswan_config()
+{
+ int i = 0;
+
+ for (i = LOCAL_IP; i < STRONGSWAN_CONF_KEY_MAX; i++)
+ g_free(strongswan_conf[i].value);
+
+ g_key_file_free(g_conf_key_file);
+ g_conf_key_file = NULL;
+}
+
+/* Run Mainloop */
+int main(int argc, char *argv[])
+{
+ int std_input_fd = 0;
+ int ret = 0;
+ __FUNC_ENTER__;
+
+ ret = load_strongswan_config(STRONGSWAN_CONF_PATH);
+ if (ret != 0) {
+ printf("Failed to load configuration. Terminate...\n");
+ return -1;
+ }
+
+ main_loop = g_main_loop_new(NULL, FALSE);
+ if (main_loop == NULL) {
+ printf("Failed to create GMainLoop structure\n");
+ return -1;
+ }
+
+ GIOChannel *unix_channel = g_io_channel_unix_new(std_input_fd);
+ g_io_add_watch(unix_channel, G_IO_IN, (GIOFunc)read_std_input, NULL);
+ g_io_channel_unref(unix_channel);
+
+ g_main_loop_run(main_loop);
+
+ unload_strongswan_config();
+
+ __FUNC_EXIT__;
+ return ret;
+}