diff options
Diffstat (limited to 'src/manager/gateway.c')
-rw-r--r-- | src/manager/gateway.c | 180 |
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; } |