diff options
Diffstat (limited to 'src/starter/confread.c')
-rw-r--r-- | src/starter/confread.c | 257 |
1 files changed, 164 insertions, 93 deletions
diff --git a/src/starter/confread.c b/src/starter/confread.c index e7a4789a9..2fe5b8ca7 100644 --- a/src/starter/confread.c +++ b/src/starter/confread.c @@ -181,14 +181,42 @@ kw_end(starter_conn_t *conn, starter_end_t *end, kw_token_t token conn->addr_family = AF_INET6; anyaddr(conn->addr_family, &end->addr); } + else if (streq(value, "%group")) + { + ip_address any; + + conn->policy |= POLICY_GROUP | POLICY_TUNNEL; + anyaddr(conn->addr_family, &end->addr); + anyaddr(conn->tunnel_addr_family, &any); + initsubnet(&any, 0, '0', &end->subnet); + end->has_client = TRUE; + } else { + bool fallback_to_any = FALSE; + + if (value[0] == '%') + { + fallback_to_any = TRUE; + end->allow_any = TRUE; + value++; + } conn->addr_family = ip_version(value); ugh = ttoaddr(value, 0, conn->addr_family, &end->addr); if (ugh != NULL) { plog("# bad addr: %s=%s [%s]", name, value, ugh); - goto err; + if (fallback_to_any) + { + plog("# fallback to %s=%%any due to '%%' prefix"); + anyaddr(conn->addr_family, &end->addr); + end->allow_any = FALSE; + cfg->non_fatal_err++; + } + else + { + goto err; + } } } break; @@ -465,11 +493,12 @@ load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg) case KW_EAP: /* TODO: a gperf function for all EAP types */ if (streq(kw->value, "aka")) + { conn->eap = 23; + } else if (streq(kw->value, "sim")) { conn->eap = 18; - } else { @@ -481,6 +510,23 @@ load_conn(starter_conn_t *conn, kw_list_t *kw, starter_config_t *cfg) } } break; + case KW_KEYINGTRIES: + if (streq(kw->value, "%forever")) + { + conn->sa_keying_tries = 0; + } + else + { + char *endptr; + + conn->sa_keying_tries = strtoul(kw->value, &endptr, 10); + if (*endptr != '\0') + { + plog("# bad integer value: %s=%s", kw->entry->name, kw->value); + cfg->err++; + } + } + break; case KW_REKEY: KW_POLICY_FLAG("no", "yes", POLICY_DONT_REKEY) break; @@ -695,7 +741,79 @@ find_also_ca(const char* name, starter_ca_t *ca, starter_config_t *cfg) return NULL; } +/* + * free the memory used by also_t objects + */ +static void +free_also(also_t *head) +{ + while (head != NULL) + { + also_t *also = head; + + head = also->next; + pfree(also->name); + pfree(also); + } +} + +/* + * free the memory used by a starter_conn_t object + */ +static void +confread_free_conn(starter_conn_t *conn) +{ + free_args(KW_END_FIRST, KW_END_LAST, (char *)&conn->left); + free_args(KW_END_FIRST, KW_END_LAST, (char *)&conn->right); + free_args(KW_CONN_NAME, KW_CONN_LAST, (char *)conn); + free_also(conn->also); +} + +/* + * free the memory used by a starter_ca_t object + */ +static void +confread_free_ca(starter_ca_t *ca) +{ + free_args(KW_CA_NAME, KW_CA_LAST, (char *)ca); + free_also(ca->also); +} + +/* + * free the memory used by a starter_config_t object + */ +void +confread_free(starter_config_t *cfg) +{ + starter_conn_t *conn = cfg->conn_first; + starter_ca_t *ca = cfg->ca_first; + + free_args(KW_SETUP_FIRST, KW_SETUP_LAST, (char *)cfg); + + confread_free_conn(&cfg->conn_default); + + while (conn != NULL) + { + starter_conn_t *conn_aux = conn; + + conn = conn->next; + confread_free_conn(conn_aux); + pfree(conn_aux); + } + + confread_free_ca(&cfg->ca_default); + + while (ca != NULL) + { + starter_ca_t *ca_aux = ca; + + ca = ca->next; + confread_free_ca(ca_aux); + pfree(ca_aux); + } + pfree(cfg); +} /* * load and parse an IPsec configuration file @@ -709,6 +827,7 @@ confread_load(const char *file) starter_conn_t *conn; starter_ca_t *ca; + u_int total_err; u_int visit = 0; /* load IPSec configuration file */ @@ -748,6 +867,8 @@ confread_load(const char *file) /* 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; @@ -761,13 +882,24 @@ confread_load(const char *file) 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; - + 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) @@ -806,6 +938,8 @@ confread_load(const char *file) /* 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; @@ -818,14 +952,25 @@ confread_load(const char *file) 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; - + + 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 */ @@ -851,86 +996,12 @@ confread_load(const char *file) parser_free_conf(cfgp); - if (cfg->err) + total_err = cfg->err + cfg->non_fatal_err; + if (total_err > 0) { - plog("### %d parsing error%s ###", cfg->err, (cfg->err > 1)?"s":""); - confread_free(cfg); - cfg = NULL; + plog("### %d parsing error%s (%d fatal) ###" + , total_err, (total_err > 1)?"s":"", cfg->err); } return cfg; } - -/* - * free the memory used by also_t objects - */ -static void -free_also(also_t *head) -{ - while (head != NULL) - { - also_t *also = head; - - head = also->next; - pfree(also->name); - pfree(also); - } -} - -/* - * free the memory used by a starter_conn_t object - */ -static void -confread_free_conn(starter_conn_t *conn) -{ - free_args(KW_END_FIRST, KW_END_LAST, (char *)&conn->left); - free_args(KW_END_FIRST, KW_END_LAST, (char *)&conn->right); - free_args(KW_CONN_NAME, KW_CONN_LAST, (char *)conn); - free_also(conn->also); -} - -/* - * free the memory used by a starter_ca_t object - */ -static void -confread_free_ca(starter_ca_t *ca) -{ - free_args(KW_CA_NAME, KW_CA_LAST, (char *)ca); - free_also(ca->also); -} - -/* - * free the memory used by a starter_config_t object - */ -void -confread_free(starter_config_t *cfg) -{ - starter_conn_t *conn = cfg->conn_first; - starter_ca_t *ca = cfg->ca_first; - - free_args(KW_SETUP_FIRST, KW_SETUP_LAST, (char *)cfg); - - confread_free_conn(&cfg->conn_default); - - while (conn != NULL) - { - starter_conn_t *conn_aux = conn; - - conn = conn->next; - confread_free_conn(conn_aux); - pfree(conn_aux); - } - - confread_free_ca(&cfg->ca_default); - - while (ca != NULL) - { - starter_ca_t *ca_aux = ca; - - ca = ca->next; - confread_free_ca(ca_aux); - pfree(ca_aux); - } - - pfree(cfg); -} |