summaryrefslogtreecommitdiff
path: root/src/manager/gateway.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/manager/gateway.c')
-rw-r--r--src/manager/gateway.c180
1 files changed, 171 insertions, 9 deletions
diff --git a/src/manager/gateway.c b/src/manager/gateway.c
index 5f5a4b477..d4eb5279e 100644
--- a/src/manager/gateway.c
+++ b/src/manager/gateway.c
@@ -57,6 +57,11 @@ struct private_gateway_t {
* socket file descriptor, > 0 if connected
*/
int fd;
+
+ /**
+ * unique id assigned to each xml message
+ */
+ int xmlid;
};
struct sockaddr_un unix_addr = { AF_UNIX, IPSEC_PIDDIR "/charon.xml"};
@@ -103,7 +108,7 @@ static bool connect_(private_gateway_t *this)
/**
* Implementation of gateway_t.request.
*/
-static char* request(private_gateway_t *this, char *xml)
+static char* request(private_gateway_t *this, char *xml, ...)
{
if (this->fd < 0)
{
@@ -116,18 +121,25 @@ static char* request(private_gateway_t *this, char *xml)
{
char buf[8096];
ssize_t len;
+ va_list args;
- len = strlen(xml);
- if (send(this->fd, xml, len, 0) != len)
+ va_start(args, xml);
+ len = vsnprintf(buf, sizeof(buf), xml, args);
+ va_end(args);
+ if (len < 0 || len >= sizeof(buf))
{
return NULL;
}
- len = recv(this->fd, buf, sizeof(buf) - 1, 0);
- if (len < 0)
+ if (send(this->fd, buf, len, 0) != len)
{
- return NULL;
+ if (!connect_(this))
+ {
+ return NULL;
+ }
+ continue;
}
- if (len == 0)
+ len = recv(this->fd, buf, sizeof(buf) - 1, 0);
+ if (len <= 0)
{
if (!connect_(this))
{
@@ -149,11 +161,11 @@ static enumerator_t* query_ikesalist(private_gateway_t *this)
xml_t *xml;
enumerator_t *e1, *e2, *e3, *e4 = NULL;
- str = request(this, "<message type=\"request\" id=\"1\">"
+ str = request(this, "<message type=\"request\" id=\"%d\">"
"<query>"
"<ikesalist/>"
"</query>"
- "</message>");
+ "</message>", this->xmlid++);
if (str == NULL)
{
return NULL;
@@ -197,6 +209,152 @@ static enumerator_t* query_ikesalist(private_gateway_t *this)
return NULL;
}
+
+/**
+ * Implementation of gateway_t.query_configlist.
+ */
+static enumerator_t* query_configlist(private_gateway_t *this)
+{
+ char *str, *name, *value;
+ xml_t *xml;
+ enumerator_t *e1, *e2, *e3, *e4 = NULL;
+
+ str = request(this, "<message type=\"request\" id=\"%d\">"
+ "<query>"
+ "<configlist/>"
+ "</query>"
+ "</message>", this->xmlid++);
+ if (str == NULL)
+ {
+ return NULL;
+ }
+ xml = xml_create(str);
+ if (xml == NULL)
+ {
+ return NULL;
+ }
+
+ e1 = xml->children(xml);
+ free(str);
+ while (e1->enumerate(e1, &xml, &name, &value))
+ {
+ if (streq(name, "message"))
+ {
+ e2 = xml->children(xml);
+ while (e2->enumerate(e2, &xml, &name, &value))
+ {
+ if (streq(name, "query"))
+ {
+ e3 = xml->children(xml);
+ while (e3->enumerate(e3, &xml, &name, &value))
+ {
+ if (streq(name, "configlist"))
+ {
+ e4 = xml->children(xml);
+ e1->destroy(e1);
+ e2->destroy(e2);
+ e3->destroy(e3);
+ return e4;
+ }
+ }
+ e3->destroy(e3);
+ }
+ }
+ e2->destroy(e2);
+ }
+ }
+ e1->destroy(e1);
+ return NULL;
+}
+
+/**
+ * create enumerator over control elements children of a control response
+ */
+static enumerator_t* read_result(private_gateway_t *this, char *res)
+{
+ char *name, *value;
+ xml_t *xml;
+ enumerator_t *e1, *e2, *e3;
+
+ if (res == NULL)
+ {
+ return NULL;
+ }
+ xml = xml_create(res);
+ if (xml == NULL)
+ {
+ return NULL;
+ }
+ e1 = xml->children(xml);
+ free(res);
+ while (e1->enumerate(e1, &xml, &name, &value))
+ {
+ if (streq(name, "message"))
+ {
+ e2 = xml->children(xml);
+ while (e2->enumerate(e2, &xml, &name, &value))
+ {
+ if (streq(name, "control"))
+ {
+ e3 = xml->children(xml);
+ e1->destroy(e1);
+ e2->destroy(e2);
+ return e3;
+ }
+ }
+ e2->destroy(e2);
+ }
+ }
+ e1->destroy(e1);
+ return NULL;
+}
+
+/**
+ * Implementation of gateway_t.initiate.
+ */
+static enumerator_t* initiate(private_gateway_t *this, bool ike, char *name)
+{
+ char *str, *kind;
+
+ if (ike)
+ {
+ kind = "ike";
+ }
+ else
+ {
+ kind = "child";
+ }
+ str = request(this, "<message type=\"request\" id=\"%d\">"
+ "<control>"
+ "<%ssainitiate>%s</%ssainitiate>"
+ "</control>"
+ "</message>", this->xmlid++, kind, name, kind);
+ return read_result(this, str);
+}
+
+/**
+ * Implementation of gateway_t.terminate.
+ */
+static enumerator_t* terminate(private_gateway_t *this, bool ike, u_int32_t id)
+{
+ char *str, *kind;
+
+ if (ike)
+ {
+ kind = "ike";
+ }
+ else
+ {
+ kind = "child";
+ }
+ str = request(this, "<message type=\"request\" id=\"%d\">"
+ "<control>"
+ "<%ssaterminate>%d</%ssaterminate>"
+ "</control>"
+ "</message>", this->xmlid++, kind, id, kind);
+ return read_result(this, str);
+}
+
/**
* Implementation of gateway_t.destroy
*/
@@ -220,11 +378,15 @@ static private_gateway_t *gateway_create(char *name)
this->public.request = (char*(*)(gateway_t*, char *xml))request;
this->public.query_ikesalist = (enumerator_t*(*)(gateway_t*))query_ikesalist;
+ this->public.query_configlist = (enumerator_t*(*)(gateway_t*))query_configlist;
+ this->public.initiate = (enumerator_t*(*)(gateway_t*, bool ike, char *name))initiate;
+ this->public.terminate = (enumerator_t*(*)(gateway_t*, bool ike, u_int32_t id))terminate;
this->public.destroy = (void(*)(gateway_t*))destroy;
this->name = strdup(name);
this->host = NULL;
this->fd = -1;
+ this->xmlid = 1;
return this;
}