support of reqid field in SQL database
[strongswan.git] / src / libcharon / plugins / sql / sql_config.c
index 2336689..9de3daa 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2006-2008 Martin Willi
+ * Copyright (C) 2010 Andreas Steffen
  * Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -38,13 +39,13 @@ struct private_sql_config_t {
 };
 
 /**
- * forward declaration
+ * Forward declaration
  */
 static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
                                                                  identification_t *me, identification_t *other);
 
 /**
- * build a traffic selector from a SQL query
+ * Build a traffic selector from an SQL query
  */
 static traffic_selector_t *build_traffic_selector(private_sql_config_t *this,
                                                                                                  enumerator_t *e, bool *local)
@@ -119,24 +120,62 @@ static void add_traffic_selectors(private_sql_config_t *this,
 }
 
 /**
- * build a Child configuration from a SQL query
+ * Add ESP proposals to a child config
+ */
+static void add_esp_proposals(private_sql_config_t *this,
+                                                         child_cfg_t *child, int id)
+{
+       enumerator_t *e;
+       proposal_t *proposal;
+       char *prop;
+       bool use_default = TRUE;
+
+       e = this->db->query(this->db,
+                       "SELECT proposal "
+                       "FROM proposals JOIN child_config_proposal ON id = prop "
+                       "WHERE child_cfg = ? ORDER BY prio",
+                       DB_INT, id, DB_TEXT);
+       if (e)
+       {
+               while (e->enumerate(e, &prop))
+               {
+                       proposal = proposal_create_from_string(PROTO_ESP, prop);
+                       if (!proposal)
+                       {
+                               DBG1(DBG_CFG, "could not create ESP proposal from '%s'", prop);
+                               break;
+                       }
+                       child->add_proposal(child, proposal);
+                       use_default = FALSE;
+               }
+               e->destroy(e);
+       }
+       if (use_default)
+       {
+               child->add_proposal(child, proposal_create_default(PROTO_ESP));
+       }
+}
+
+/**
+ * Build a child config from an SQL query
  */
 static child_cfg_t *build_child_cfg(private_sql_config_t *this, enumerator_t *e)
 {
-       int id, lifetime, rekeytime, jitter, hostaccess, mode, dpd, close, ipcomp;
+       int id, lifetime, rekeytime, jitter, hostaccess, mode, ipcomp, reqid;
+       int start, dpd, close;
        char *name, *updown;
        child_cfg_t *child_cfg;
 
-       if (e->enumerate(e, &id, &name, &lifetime, &rekeytime, &jitter,
-                                               &updown, &hostaccess, &mode, &dpd, &close, &ipcomp))
+       if (e->enumerate(e, &id, &name, &lifetime, &rekeytime, &jitter, &updown,
+                                               &hostaccess, &mode, &start, &dpd, &close, &ipcomp, %reqid))
        {
                lifetime_cfg_t lft = {
                        .time = { .life = lifetime, .rekey = rekeytime, .jitter = jitter }
                };
                child_cfg = child_cfg_create(name, &lft, updown, hostaccess, mode,
-                                                                        dpd, close, ipcomp, 0);
-               /* TODO: read proposal from db */
-               child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
+                                                                        start, dpd, close, ipcomp, 0, reqid,
+                                                                        NULL, NULL);
+               add_esp_proposals(this, child_cfg, id);
                add_traffic_selectors(this, child_cfg, id);
                return child_cfg;
        }
@@ -152,13 +191,13 @@ static void add_child_cfgs(private_sql_config_t *this, peer_cfg_t *peer, int id)
        child_cfg_t *child_cfg;
 
        e = this->db->query(this->db,
-                       "SELECT id, name, lifetime, rekeytime, jitter, "
-                       "updown, hostaccess, mode, dpd_action, close_action, ipcomp "
+                       "SELECT id, name, lifetime, rekeytime, jitter, updown, hostaccess, "
+                       "mode, start_action, dpd_action, close_action, ipcomp, reqid "
                        "FROM child_configs JOIN peer_config_child_config ON id = child_cfg "
                        "WHERE peer_cfg = ?",
                        DB_INT, id,
-                       DB_INT, DB_TEXT, DB_INT, DB_INT, DB_INT,
-                       DB_TEXT, DB_INT, DB_INT, DB_INT, DB_INT, DB_INT);
+                       DB_INT, DB_TEXT, DB_INT, DB_INT, DB_INT, DB_TEXT, DB_INT,
+                       DB_INT, DB_INT, DB_INT, DB_INT, DB_INT, DB_INT);
        if (e)
        {
                while ((child_cfg = build_child_cfg(this, e)))
@@ -170,29 +209,65 @@ static void add_child_cfgs(private_sql_config_t *this, peer_cfg_t *peer, int id)
 }
 
 /**
- * build a ike configuration from a SQL query
+ * Add IKE proposals to an IKE config
+ */
+static void add_ike_proposals(private_sql_config_t *this,
+                                                         ike_cfg_t *ike_cfg, int id)
+{
+       enumerator_t *e;
+       proposal_t *proposal;
+       char *prop;
+       bool use_default = TRUE;
+
+       e = this->db->query(this->db,
+                       "SELECT proposal "
+                       "FROM proposals JOIN ike_config_proposal ON id = prop "
+                       "WHERE ike_cfg = ? ORDER BY prio",
+                       DB_INT, id, DB_TEXT);
+       if (e)
+       {
+               while (e->enumerate(e, &prop))
+               {
+                       proposal = proposal_create_from_string(PROTO_IKE, prop);
+                       if (!proposal)
+                       {
+                               DBG1(DBG_CFG, "could not create IKE proposal from '%s'", prop);
+                               break;
+                       }
+                       ike_cfg->add_proposal(ike_cfg, proposal);
+                       use_default = FALSE;
+               }
+               e->destroy(e);
+       }
+       if (use_default)
+       {
+               ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
+       }
+}
+
+/**
+ * Build an IKE config from an SQL query
  */
 static ike_cfg_t *build_ike_cfg(private_sql_config_t *this, enumerator_t *e,
                                                                host_t *my_host, host_t *other_host)
 {
-       int certreq, force_encap;
+       int id, certreq, force_encap;
        char *local, *remote;
 
-       while (e->enumerate(e, &certreq, &force_encap, &local, &remote))
+       while (e->enumerate(e, &id, &certreq, &force_encap, &local, &remote))
        {
                ike_cfg_t *ike_cfg;
 
                ike_cfg = ike_cfg_create(certreq, force_encap,
                                                                 local, IKEV2_UDP_PORT, remote, IKEV2_UDP_PORT);
-               /* TODO: read proposal from db */
-               ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
+               add_ike_proposals(this, ike_cfg, id);
                return ike_cfg;
        }
        return NULL;
 }
 
 /**
- * Query a IKE config by its id
+ * Query an IKE config by its id
  */
 static ike_cfg_t* get_ike_cfg_by_id(private_sql_config_t *this, int id)
 {
@@ -200,10 +275,10 @@ static ike_cfg_t* get_ike_cfg_by_id(private_sql_config_t *this, int id)
        ike_cfg_t *ike_cfg = NULL;
 
        e = this->db->query(this->db,
-                       "SELECT certreq, force_encap, local, remote "
+                       "SELECT id, certreq, force_encap, local, remote "
                        "FROM ike_configs WHERE id = ?",
                        DB_INT, id,
-                       DB_INT, DB_INT, DB_TEXT, DB_TEXT);
+                       DB_INT, DB_INT, DB_INT, DB_TEXT, DB_TEXT);
        if (e)
        {
                ike_cfg = build_ike_cfg(this, e, NULL, NULL);
@@ -246,7 +321,7 @@ static peer_cfg_t *get_peer_cfg_by_id(private_sql_config_t *this, int id)
 }
 
 /**
- * build a peer configuration from a SQL query
+ * Build a peer config from an SQL query
  */
 static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
                                                                  identification_t *me, identification_t *other)
@@ -325,10 +400,8 @@ static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
        return NULL;
 }
 
-/**
- * implements backend_t.get_peer_cfg_by_name.
- */
-static peer_cfg_t *get_peer_cfg_by_name(private_sql_config_t *this, char *name)
+METHOD(backend_t, get_peer_cfg_by_name, peer_cfg_t*,
+       private_sql_config_t *this, char *name)
 {
        enumerator_t *e;
        peer_cfg_t *peer_cfg = NULL;
@@ -398,11 +471,8 @@ static void ike_enumerator_destroy(ike_enumerator_t *this)
        free(this);
 }
 
-/**
- * Implementation of backend_t.create_ike_cfg_enumerator.
- */
-static enumerator_t* create_ike_cfg_enumerator(private_sql_config_t *this,
-                                                                                          host_t *me, host_t *other)
+METHOD(backend_t, create_ike_cfg_enumerator, enumerator_t*,
+       private_sql_config_t *this, host_t *me, host_t *other)
 {
        ike_enumerator_t *e = malloc_thing(ike_enumerator_t);
 
@@ -414,9 +484,9 @@ static enumerator_t* create_ike_cfg_enumerator(private_sql_config_t *this,
        e->public.destroy = (void*)ike_enumerator_destroy;
 
        e->inner = this->db->query(this->db,
-                       "SELECT certreq, force_encap, local, remote "
+                       "SELECT id, certreq, force_encap, local, remote "
                        "FROM ike_configs",
-                       DB_INT, DB_INT, DB_TEXT, DB_TEXT);
+                       DB_INT, DB_INT, DB_INT, DB_TEXT, DB_TEXT);
        if (!e->inner)
        {
                free(e);
@@ -466,12 +536,8 @@ static void peer_enumerator_destroy(peer_enumerator_t *this)
        free(this);
 }
 
-/**
- * Implementation of backend_t.create_peer_cfg_enumerator.
- */
-static enumerator_t* create_peer_cfg_enumerator(private_sql_config_t *this,
-                                                                                               identification_t *me,
-                                                                                               identification_t *other)
+METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
+       private_sql_config_t *this, identification_t *me, identification_t *other)
 {
        peer_enumerator_t *e = malloc_thing(peer_enumerator_t);
 
@@ -508,10 +574,8 @@ static enumerator_t* create_peer_cfg_enumerator(private_sql_config_t *this,
        return &e->public;
 }
 
-/**
- * Implementation of sql_config_t.destroy.
- */
-static void destroy(private_sql_config_t *this)
+METHOD(sql_config_t, destroy, void,
+       private_sql_config_t *this)
 {
        free(this);
 }
@@ -521,14 +585,19 @@ static void destroy(private_sql_config_t *this)
  */
 sql_config_t *sql_config_create(database_t *db)
 {
-       private_sql_config_t *this = malloc_thing(private_sql_config_t);
-
-       this->public.backend.create_peer_cfg_enumerator = (enumerator_t*(*)(backend_t*, identification_t *me, identification_t *other))create_peer_cfg_enumerator;
-       this->public.backend.create_ike_cfg_enumerator = (enumerator_t*(*)(backend_t*, host_t *me, host_t *other))create_ike_cfg_enumerator;
-       this->public.backend.get_peer_cfg_by_name = (peer_cfg_t* (*)(backend_t*,char*))get_peer_cfg_by_name;
-       this->public.destroy = (void(*)(sql_config_t*))destroy;
+       private_sql_config_t *this;
 
-       this->db = db;
+       INIT(this,
+               .public = {
+                       .backend = {
+                               .create_peer_cfg_enumerator = _create_peer_cfg_enumerator,
+                               .create_ike_cfg_enumerator = _create_ike_cfg_enumerator,
+                               .get_peer_cfg_by_name = _get_peer_cfg_by_name,
+                       },
+                       .destroy = _destroy,
+               },
+               .db = db
+       );
 
        return &this->public;
 }