ECB mode added to the DES plugin
[strongswan.git] / src / manager / gateway.c
index 5f5a4b4..6d5f6f7 100644 (file)
@@ -1,10 +1,3 @@
-/**
- * @file gateway.c
- *
- * @brief Implementation of gateway_t.
- *
- */
-
 /*
  * Copyright (C) 2007 Martin Willi
  * Hochschule fuer Technik Rapperswil
@@ -18,6 +11,8 @@
  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  * for more details.
+ *
+ * $Id$
  */
 
 #include "gateway.h"
@@ -29,7 +24,7 @@
 #include <sys/socket.h>
 #include <sys/un.h>
 
-#include <lib/xml.h>
+#include <xml.h>
 
 typedef struct private_gateway_t private_gateway_t;
 
@@ -57,6 +52,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 +103,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 +116,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 +156,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 +204,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 +373,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;
 }