diff --git a/src/starter/confread.c b/src/starter/confread.c index e7a4789a9..76d085513 100644 --- a/src/starter/confread.c +++ b/src/starter/confread.c @@ -695,172 +695,6 @@ find_also_ca(const char* name, starter_ca_t *ca, starter_config_t *cfg) return NULL; } - - -/* - * load and parse an IPsec configuration file - */ -starter_config_t * -confread_load(const char *file) -{ - starter_config_t *cfg = NULL; - config_parsed_t *cfgp; - section_list_t *sconn, *sca; - starter_conn_t *conn; - starter_ca_t *ca; - - u_int visit = 0; - - /* load IPSec configuration file */ - cfgp = parser_load_conf(file); - if (!cfgp) - return NULL; - - cfg = (starter_config_t *)alloc_thing(starter_config_t, "starter_config_t"); - - /* set default values */ - default_values(cfg); - - /* determine default route */ - get_defaultroute(&cfg->defaultroute); - - /* load config setup section */ - load_setup(cfg, cfgp); - - /* in the first round parse also statements */ - cfg->parse_also = TRUE; - - /* find %default ca section */ - for (sca = cfgp->ca_first; sca; sca = sca->next) - { - if (streq(sca->name, "%default")) - { - DBG(DBG_CONTROL, - DBG_log("Loading ca %%default") - ) - load_ca(&cfg->ca_default, sca->kw, cfg); - } - } - - /* parameters defined in ca %default sections can be overloads */ - cfg->ca_default.seen = LEMPTY; - - /* load other ca sections */ - for (sca = cfgp->ca_first; sca; sca = sca->next) - { - /* skip %default ca section */ - if (streq(sca->name, "%default")) - continue; - - DBG(DBG_CONTROL, - DBG_log("Loading ca '%s'", sca->name) - ) - ca = (starter_ca_t *)alloc_thing(starter_ca_t, "starter_ca_t"); - - ca_default(sca->name, ca, &cfg->ca_default); - ca->kw = sca->kw; - ca->next = NULL; - - if (cfg->ca_last) - cfg->ca_last->next = ca; - cfg->ca_last = ca; - if (!cfg->ca_first) - cfg->ca_first = ca; - - load_ca(ca, ca->kw, cfg); - } - - for (ca = cfg->ca_first; ca; ca = ca->next) - { - also_t *also = ca->also; - - while (also != NULL) - { - kw_list_t *kw = find_also_ca(also->name, cfg->ca_first, cfg); - - load_ca(ca, kw, cfg); - also = also->next; - } - - if (ca->startup != STARTUP_NO) - ca->state = STATE_TO_ADD; - } - - /* find %default conn sections */ - for (sconn = cfgp->conn_first; sconn; sconn = sconn->next) - { - if (streq(sconn->name, "%default")) - { - DBG(DBG_CONTROL, - DBG_log("Loading conn %%default") - ) - load_conn(&cfg->conn_default, sconn->kw, cfg); - } - } - - /* parameter defined in conn %default sections can be overloaded */ - cfg->conn_default.seen = LEMPTY; - cfg->conn_default.right.seen = LEMPTY; - cfg->conn_default.left.seen = LEMPTY; - - /* load other conn sections */ - for (sconn = cfgp->conn_first; sconn; sconn = sconn->next) - { - /* skip %default conn section */ - if (streq(sconn->name, "%default")) - continue; - - DBG(DBG_CONTROL, - DBG_log("Loading conn '%s'", sconn->name) - ) - conn = (starter_conn_t *)alloc_thing(starter_conn_t, "starter_conn_t"); - - conn_default(sconn->name, conn, &cfg->conn_default); - conn->kw = sconn->kw; - conn->next = NULL; - - if (cfg->conn_last) - cfg->conn_last->next = conn; - cfg->conn_last = conn; - if (!cfg->conn_first) - cfg->conn_first = conn; - - load_conn(conn, conn->kw, cfg); - } - - /* in the second round do not parse also statements */ - cfg->parse_also = FALSE; - - for (ca = cfg->ca_first; ca; ca = ca->next) - { - ca->visit = ++visit; - load_also_cas(ca, ca->also, cfg); - - if (ca->startup != STARTUP_NO) - ca->state = STATE_TO_ADD; - } - - for (conn = cfg->conn_first; conn; conn = conn->next) - { - conn->visit = ++visit; - load_also_conns(conn, conn->also, cfg); - - if (conn->startup != STARTUP_NO) - conn->state = STATE_TO_ADD; - } - - parser_free_conf(cfgp); - - if (cfg->err) - { - plog("### %d parsing error%s ###", cfg->err, (cfg->err > 1)?"s":""); - confread_free(cfg); - cfg = NULL; - } - - return cfg; -} - /* * free the memory used by also_t objects */ @@ -934,3 +768,194 @@ confread_free(starter_config_t *cfg) pfree(cfg); } + +/* + * load and parse an IPsec configuration file + */ +starter_config_t * +confread_load(const char *file) +{ + starter_config_t *cfg = NULL; + config_parsed_t *cfgp; + section_list_t *sconn, *sca; + starter_conn_t *conn; + starter_ca_t *ca; + + u_int total_err; + u_int visit = 0; + + /* load IPSec configuration file */ + cfgp = parser_load_conf(file); + if (!cfgp) + return NULL; + + cfg = (starter_config_t *)alloc_thing(starter_config_t, "starter_config_t"); + + /* set default values */ + default_values(cfg); + + /* determine default route */ + get_defaultroute(&cfg->defaultroute); + + /* load config setup section */ + load_setup(cfg, cfgp); + + /* in the first round parse also statements */ + cfg->parse_also = TRUE; + + /* find %default ca section */ + for (sca = cfgp->ca_first; sca; sca = sca->next) + { + if (streq(sca->name, "%default")) + { + DBG(DBG_CONTROL, + DBG_log("Loading ca %%default") + ) + load_ca(&cfg->ca_default, sca->kw, cfg); + } + } + + /* parameters defined in ca %default sections can be overloads */ + cfg->ca_default.seen = LEMPTY; + + /* load other ca sections */ + for (sca = cfgp->ca_first; sca; sca = sca->next) + { + u_int previous_err; + + /* skip %default ca section */ + if (streq(sca->name, "%default")) + continue; + + DBG(DBG_CONTROL, + DBG_log("Loading ca '%s'", sca->name) + ) + ca = (starter_ca_t *)alloc_thing(starter_ca_t, "starter_ca_t"); + + ca_default(sca->name, ca, &cfg->ca_default); + ca->kw = sca->kw; + ca->next = NULL; + + previous_err = cfg->err; + load_ca(ca, ca->kw, cfg); + if (cfg->err > previous_err) + { + /* errors occurred - free the ca */ + confread_free_ca(ca); + cfg->non_fatal_err += cfg->err - previous_err; + cfg->err = previous_err; + } + else + { + /* success - insert the ca into the chained list */ + if (cfg->ca_last) + cfg->ca_last->next = ca; + cfg->ca_last = ca; + if (!cfg->ca_first) + cfg->ca_first = ca; + } + } + + for (ca = cfg->ca_first; ca; ca = ca->next) + { + also_t *also = ca->also; + + while (also != NULL) + { + kw_list_t *kw = find_also_ca(also->name, cfg->ca_first, cfg); + + load_ca(ca, kw, cfg); + also = also->next; + } + + if (ca->startup != STARTUP_NO) + ca->state = STATE_TO_ADD; + } + + /* find %default conn sections */ + for (sconn = cfgp->conn_first; sconn; sconn = sconn->next) + { + if (streq(sconn->name, "%default")) + { + DBG(DBG_CONTROL, + DBG_log("Loading conn %%default") + ) + load_conn(&cfg->conn_default, sconn->kw, cfg); + } + } + + /* parameter defined in conn %default sections can be overloaded */ + cfg->conn_default.seen = LEMPTY; + cfg->conn_default.right.seen = LEMPTY; + cfg->conn_default.left.seen = LEMPTY; + + /* load other conn sections */ + for (sconn = cfgp->conn_first; sconn; sconn = sconn->next) + { + u_int previous_err; + + /* skip %default conn section */ + if (streq(sconn->name, "%default")) + continue; + + DBG(DBG_CONTROL, + DBG_log("Loading conn '%s'", sconn->name) + ) + conn = (starter_conn_t *)alloc_thing(starter_conn_t, "starter_conn_t"); + + conn_default(sconn->name, conn, &cfg->conn_default); + conn->kw = sconn->kw; + conn->next = NULL; + + previous_err = cfg->err; + load_conn(conn, conn->kw, cfg); + if (cfg->err > previous_err) + { + /* error occurred - free the conn */ + confread_free_conn(conn); + cfg->non_fatal_err += cfg->err - previous_err; + cfg->err = previous_err; + } + else + { + /* success - insert the conn into the chained list */ + if (cfg->conn_last) + cfg->conn_last->next = conn; + cfg->conn_last = conn; + if (!cfg->conn_first) + cfg->conn_first = conn; + } + } + + /* in the second round do not parse also statements */ + cfg->parse_also = FALSE; + + for (ca = cfg->ca_first; ca; ca = ca->next) + { + ca->visit = ++visit; + load_also_cas(ca, ca->also, cfg); + + if (ca->startup != STARTUP_NO) + ca->state = STATE_TO_ADD; + } + + for (conn = cfg->conn_first; conn; conn = conn->next) + { + conn->visit = ++visit; + load_also_conns(conn, conn->also, cfg); + + if (conn->startup != STARTUP_NO) + conn->state = STATE_TO_ADD; + } + + parser_free_conf(cfgp); + + total_err = cfg->err + cfg->non_fatal_err; + if (total_err > 0) + { + plog("### %d parsing error%s (%d fatal) ###" + , total_err, (total_err > 1)?"s":"", cfg->err); + } + + return cfg; +} diff --git a/src/starter/confread.h b/src/starter/confread.h index c0993f2b3..99851d5b6 100644 --- a/src/starter/confread.h +++ b/src/starter/confread.h @@ -192,7 +192,8 @@ struct starter_config { defaultroute_t defaultroute; /* number of encountered parsing errors */ - u_int err; + u_int err; + u_int non_fatal_err; /* do we parse also statements */ bool parse_also; diff --git a/src/starter/starter.c b/src/starter/starter.c index f84d41380..650ace34a 100644 --- a/src/starter/starter.c +++ b/src/starter/starter.c @@ -237,9 +237,10 @@ int main (int argc, char **argv) } cfg = confread_load(CONFIG_FILE); - if (!cfg) + if (cfg->err > 0) { - plog("unable to start strongSwan -- errors in config"); + plog("unable to start strongSwan -- fatal errors in config"); + confread_free(cfg); exit(1); } @@ -373,7 +374,7 @@ int main (int argc, char **argv) ); new_cfg = confread_load(CONFIG_FILE); - if (new_cfg) + if (new_cfg->err + new_cfg->non_fatal_err == 0) { /* Switch to new config. New conn will be loaded below */ if (!starter_cmp_defaultroute(&new_cfg->defaultroute @@ -466,7 +467,8 @@ int main (int argc, char **argv) } else { - plog("can't reload config file: %s -- keeping old one"); + plog("can't reload config file due to errors -- keeping old one"); + confread_free(new_cfg); } _action_ &= ~FLAG_ACTION_UPDATE; last_reload = time(NULL);