Return to confread.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / starter |
1.1 ! misho 1: /* ! 2: * Copyright (C) 2014 Tobias Brunner ! 3: * HSR Hochschule fuer Technik Rapperswil ! 4: * ! 5: * Copyright (C) 2001-2002 Mathieu Lafon - Arkoon Network Security ! 6: * ! 7: * This program is free software; you can redistribute it and/or modify it ! 8: * under the terms of the GNU General Public License as published by the ! 9: * Free Software Foundation; either version 2 of the License, or (at your ! 10: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ! 11: * ! 12: * This program is distributed in the hope that it will be useful, but ! 13: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ! 14: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ! 15: * for more details. ! 16: */ ! 17: ! 18: #include <sys/types.h> ! 19: #include <sys/stat.h> ! 20: #include <unistd.h> ! 21: #include <stddef.h> ! 22: #include <stdlib.h> ! 23: #include <string.h> ! 24: #include <assert.h> ! 25: #include <netdb.h> ! 26: ! 27: #include <library.h> ! 28: #include <utils/debug.h> ! 29: ! 30: #include "keywords.h" ! 31: #include "confread.h" ! 32: #include "args.h" ! 33: #include "files.h" ! 34: #include "parser/conf_parser.h" ! 35: ! 36: #define IKE_LIFETIME_DEFAULT 10800 /* 3 hours */ ! 37: #define IPSEC_LIFETIME_DEFAULT 3600 /* 1 hour */ ! 38: #define SA_REPLACEMENT_MARGIN_DEFAULT 540 /* 9 minutes */ ! 39: #define SA_REPLACEMENT_FUZZ_DEFAULT 100 /* 100% of margin */ ! 40: #define SA_REPLACEMENT_RETRIES_DEFAULT 3 ! 41: #define SA_REPLAY_WINDOW_DEFAULT -1 /* use charon.replay_window */ ! 42: ! 43: static const char firewall_defaults[] = IPSEC_SCRIPT " _updown iptables"; ! 44: ! 45: /** ! 46: * Process deprecated keywords ! 47: */ ! 48: static bool is_deprecated(kw_token_t token, char *name, char *conn) ! 49: { ! 50: switch (token) ! 51: { ! 52: case KW_SETUP_DEPRECATED: ! 53: case KW_PKCS11_DEPRECATED: ! 54: DBG1(DBG_APP, "# deprecated keyword '%s' in config setup", name); ! 55: break; ! 56: case KW_CONN_DEPRECATED: ! 57: case KW_END_DEPRECATED: ! 58: case KW_PFS_DEPRECATED: ! 59: DBG1(DBG_APP, "# deprecated keyword '%s' in conn '%s'", name, conn); ! 60: break; ! 61: case KW_CA_DEPRECATED: ! 62: DBG1(DBG_APP, "# deprecated keyword '%s' in ca '%s'", name, conn); ! 63: break; ! 64: default: ! 65: return FALSE; ! 66: } ! 67: /* additional messages for some */ ! 68: switch (token) ! 69: { ! 70: case KW_PKCS11_DEPRECATED: ! 71: DBG1(DBG_APP, " use the 'pkcs11' plugin instead"); ! 72: break; ! 73: case KW_PFS_DEPRECATED: ! 74: DBG1(DBG_APP, " PFS is enabled by specifying a DH group in the " ! 75: "'esp' cipher suite"); ! 76: break; ! 77: default: ! 78: break; ! 79: } ! 80: return TRUE; ! 81: } ! 82: ! 83: /* ! 84: * parse config setup section ! 85: */ ! 86: static void load_setup(starter_config_t *cfg, conf_parser_t *parser) ! 87: { ! 88: enumerator_t *enumerator; ! 89: dictionary_t *dict; ! 90: const kw_entry_t *entry; ! 91: char *key, *value; ! 92: ! 93: DBG2(DBG_APP, "Loading config setup"); ! 94: dict = parser->get_section(parser, CONF_PARSER_CONFIG_SETUP, NULL); ! 95: if (!dict) ! 96: { ! 97: return; ! 98: } ! 99: enumerator = dict->create_enumerator(dict); ! 100: while (enumerator->enumerate(enumerator, &key, &value)) ! 101: { ! 102: bool assigned = FALSE; ! 103: ! 104: entry = in_word_set(key, strlen(key)); ! 105: if (!entry) ! 106: { ! 107: DBG1(DBG_APP, "# unknown keyword '%s'", key); ! 108: cfg->non_fatal_err++; ! 109: continue; ! 110: } ! 111: if ((int)entry->token < KW_SETUP_FIRST || entry->token > KW_SETUP_LAST) ! 112: { ! 113: DBG1(DBG_APP, "# unsupported keyword '%s' in config setup", key); ! 114: cfg->err++; ! 115: continue; ! 116: } ! 117: if (is_deprecated(entry->token, key, "")) ! 118: { ! 119: cfg->non_fatal_err++; ! 120: continue; ! 121: } ! 122: if (!assign_arg(entry->token, KW_SETUP_FIRST, key, value, cfg, ! 123: &assigned)) ! 124: { ! 125: DBG1(DBG_APP, " bad argument value in config setup"); ! 126: cfg->err++; ! 127: } ! 128: } ! 129: enumerator->destroy(enumerator); ! 130: dict->destroy(dict); ! 131: } ! 132: ! 133: /* ! 134: * parse a ca section ! 135: */ ! 136: static void load_ca(starter_ca_t *ca, starter_config_t *cfg, ! 137: conf_parser_t *parser) ! 138: { ! 139: enumerator_t *enumerator; ! 140: dictionary_t *dict; ! 141: const kw_entry_t *entry; ! 142: kw_token_t token; ! 143: char *key, *value; ! 144: ! 145: DBG2(DBG_APP, "Loading ca '%s'", ca->name); ! 146: dict = parser->get_section(parser, CONF_PARSER_CA, ca->name); ! 147: if (!dict) ! 148: { ! 149: return; ! 150: } ! 151: enumerator = dict->create_enumerator(dict); ! 152: while (enumerator->enumerate(enumerator, &key, &value)) ! 153: { ! 154: bool assigned = FALSE; ! 155: ! 156: entry = in_word_set(key, strlen(key)); ! 157: if (!entry) ! 158: { ! 159: DBG1(DBG_APP, "# unknown keyword '%s'", key); ! 160: cfg->non_fatal_err++; ! 161: continue; ! 162: } ! 163: token = entry->token; ! 164: if (token == KW_AUTO) ! 165: { ! 166: token = KW_CA_SETUP; ! 167: } ! 168: if (token < KW_CA_FIRST || token > KW_CA_LAST) ! 169: { ! 170: DBG1(DBG_APP, "# unsupported keyword '%s' in ca '%s'", ! 171: key, ca->name); ! 172: cfg->err++; ! 173: continue; ! 174: } ! 175: if (is_deprecated(token, key, ca->name)) ! 176: { ! 177: cfg->non_fatal_err++; ! 178: continue; ! 179: } ! 180: if (!assign_arg(token, KW_CA_FIRST, key, value, ca, &assigned)) ! 181: { ! 182: DBG1(DBG_APP, " bad argument value in ca '%s'", ca->name); ! 183: cfg->err++; ! 184: } ! 185: } ! 186: enumerator->destroy(enumerator); ! 187: dict->destroy(dict); ! 188: ! 189: /* treat 'route' and 'start' as 'add' */ ! 190: if (ca->startup != STARTUP_NO) ! 191: { ! 192: ca->startup = STARTUP_ADD; ! 193: } ! 194: } ! 195: ! 196: /* ! 197: * set some default values ! 198: */ ! 199: static void conn_defaults(starter_conn_t *conn) ! 200: { ! 201: conn->startup = STARTUP_NO; ! 202: conn->state = STATE_IGNORE; ! 203: conn->mode = MODE_TUNNEL; ! 204: conn->options = SA_OPTION_MOBIKE; ! 205: ! 206: /* esp defaults are set after parsing the conn section */ ! 207: conn->sa_ike_life_seconds = IKE_LIFETIME_DEFAULT; ! 208: conn->sa_ipsec_life_seconds = IPSEC_LIFETIME_DEFAULT; ! 209: conn->sa_rekey_margin = SA_REPLACEMENT_MARGIN_DEFAULT; ! 210: conn->sa_rekey_fuzz = SA_REPLACEMENT_FUZZ_DEFAULT; ! 211: conn->sa_keying_tries = SA_REPLACEMENT_RETRIES_DEFAULT; ! 212: conn->install_policy = TRUE; ! 213: conn->dpd_delay = 30; /* seconds */ ! 214: conn->dpd_timeout = 150; /* seconds */ ! 215: conn->replay_window = SA_REPLAY_WINDOW_DEFAULT; ! 216: conn->fragmentation = FRAGMENTATION_YES; ! 217: ! 218: conn->left.sendcert = CERT_SEND_IF_ASKED; ! 219: conn->right.sendcert = CERT_SEND_IF_ASKED; ! 220: ! 221: conn->left.ikeport = 500; ! 222: conn->right.ikeport = 500; ! 223: ! 224: conn->left.to_port = 0xffff; ! 225: conn->right.to_port = 0xffff; ! 226: } ! 227: ! 228: /* ! 229: * parse left|right specific options ! 230: */ ! 231: static void kw_end(starter_conn_t *conn, starter_end_t *end, kw_token_t token, ! 232: char *key, char *value, starter_config_t *cfg) ! 233: { ! 234: bool assigned = FALSE; ! 235: ! 236: if (is_deprecated(token, key, conn->name)) ! 237: { ! 238: cfg->non_fatal_err++; ! 239: return; ! 240: } ! 241: ! 242: if (!assign_arg(token, KW_END_FIRST, key, value, end, &assigned)) ! 243: { ! 244: goto err; ! 245: } ! 246: ! 247: /* post processing of some keywords that were assigned automatically */ ! 248: switch (token) ! 249: { ! 250: case KW_HOST: ! 251: if (value && strlen(value) > 0 && value[0] == '%') ! 252: { ! 253: if (streq(value, "%defaultroute")) ! 254: { ! 255: value = "%any"; ! 256: } ! 257: if (!streq(value, "%any") && !streq(value, "%any4") && ! 258: !streq(value, "%any6")) ! 259: { /* allow_any prefix */ ! 260: end->allow_any = TRUE; ! 261: value++; ! 262: } ! 263: } ! 264: free(end->host); ! 265: end->host = strdupnull(value); ! 266: break; ! 267: case KW_SOURCEIP: ! 268: conn->mode = MODE_TUNNEL; ! 269: conn->proxy_mode = FALSE; ! 270: break; ! 271: case KW_SENDCERT: ! 272: if (end->sendcert == CERT_YES_SEND) ! 273: { ! 274: end->sendcert = CERT_ALWAYS_SEND; ! 275: } ! 276: else if (end->sendcert == CERT_NO_SEND) ! 277: { ! 278: end->sendcert = CERT_NEVER_SEND; ! 279: } ! 280: break; ! 281: default: ! 282: break; ! 283: } ! 284: ! 285: if (assigned) ! 286: { ! 287: return; ! 288: } ! 289: ! 290: /* individual processing of keywords that were not assigned automatically */ ! 291: switch (token) ! 292: { ! 293: case KW_PROTOPORT: ! 294: { ! 295: struct protoent *proto; ! 296: struct servent *svc; ! 297: char *sep, *port = "", *endptr; ! 298: long int p; ! 299: ! 300: sep = strchr(value, '/'); ! 301: if (sep) ! 302: { /* protocol/port */ ! 303: *sep = '\0'; ! 304: port = sep + 1; ! 305: } ! 306: ! 307: if (streq(value, "%any")) ! 308: { ! 309: end->protocol = 0; ! 310: } ! 311: else ! 312: { ! 313: proto = getprotobyname(value); ! 314: if (proto) ! 315: { ! 316: end->protocol = proto->p_proto; ! 317: } ! 318: else ! 319: { ! 320: p = strtol(value, &endptr, 0); ! 321: if ((*value && *endptr) || p < 0 || p > 0xff) ! 322: { ! 323: DBG1(DBG_APP, "# bad protocol: %s=%s", key, value); ! 324: goto err; ! 325: } ! 326: end->protocol = (uint8_t)p; ! 327: } ! 328: } ! 329: if (streq(port, "%any")) ! 330: { ! 331: end->from_port = 0; ! 332: end->to_port = 0xffff; ! 333: } ! 334: else if (streq(port, "%opaque")) ! 335: { ! 336: end->from_port = 0xffff; ! 337: end->to_port = 0; ! 338: } ! 339: else if (*port) ! 340: { ! 341: svc = getservbyname(port, NULL); ! 342: if (svc) ! 343: { ! 344: end->from_port = end->to_port = ntohs(svc->s_port); ! 345: } ! 346: else ! 347: { ! 348: p = strtol(port, &endptr, 0); ! 349: if (p < 0 || p > 0xffff) ! 350: { ! 351: DBG1(DBG_APP, "# bad port: %s=%s", key, port); ! 352: goto err; ! 353: } ! 354: end->from_port = p; ! 355: if (*endptr == '-') ! 356: { ! 357: port = endptr + 1; ! 358: p = strtol(port, &endptr, 0); ! 359: if (p < 0 || p > 0xffff) ! 360: { ! 361: DBG1(DBG_APP, "# bad port: %s=%s", key, port); ! 362: goto err; ! 363: } ! 364: } ! 365: end->to_port = p; ! 366: if (*endptr) ! 367: { ! 368: DBG1(DBG_APP, "# bad port: %s=%s", key, port); ! 369: goto err; ! 370: } ! 371: } ! 372: } ! 373: if (sep) ! 374: { /* restore the original text in case also= is used */ ! 375: *sep = '/'; ! 376: } ! 377: break; ! 378: } ! 379: default: ! 380: break; ! 381: } ! 382: return; ! 383: ! 384: err: ! 385: DBG1(DBG_APP, " bad argument value in conn '%s'", conn->name); ! 386: cfg->err++; ! 387: } ! 388: ! 389: /* ! 390: * macro to handle simple flags ! 391: */ ! 392: #define KW_SA_OPTION_FLAG(sy, sn, fl) \ ! 393: if (streq(value, sy)) { conn->options |= fl; } \ ! 394: else if (streq(value, sn)) { conn->options &= ~fl; } \ ! 395: else { DBG1(DBG_APP, "# bad option value: %s=%s", key, value); cfg->err++; } ! 396: ! 397: /* ! 398: * parse settings not handled by the simple argument parser ! 399: */ ! 400: static void handle_keyword(kw_token_t token, starter_conn_t *conn, char *key, ! 401: char *value, starter_config_t *cfg) ! 402: { ! 403: if ((token == KW_ESP && conn->ah) || (token == KW_AH && conn->esp)) ! 404: { ! 405: DBG1(DBG_APP, "# can't have both 'ah' and 'esp' options"); ! 406: cfg->err++; ! 407: return; ! 408: } ! 409: switch (token) ! 410: { ! 411: case KW_TYPE: ! 412: { ! 413: conn->mode = MODE_TRANSPORT; ! 414: conn->proxy_mode = FALSE; ! 415: if (streq(value, "tunnel")) ! 416: { ! 417: conn->mode = MODE_TUNNEL; ! 418: } ! 419: else if (streq(value, "beet")) ! 420: { ! 421: conn->mode = MODE_BEET; ! 422: } ! 423: else if (streq(value, "transport_proxy")) ! 424: { ! 425: conn->mode = MODE_TRANSPORT; ! 426: conn->proxy_mode = TRUE; ! 427: } ! 428: else if (streq(value, "passthrough") || streq(value, "pass")) ! 429: { ! 430: conn->mode = MODE_PASS; ! 431: } ! 432: else if (streq(value, "drop") || streq(value, "reject")) ! 433: { ! 434: conn->mode = MODE_DROP; ! 435: } ! 436: else if (!streq(value, "transport")) ! 437: { ! 438: DBG1(DBG_APP, "# bad policy value: %s=%s", key, value); ! 439: cfg->err++; ! 440: } ! 441: break; ! 442: } ! 443: case KW_COMPRESS: ! 444: KW_SA_OPTION_FLAG("yes", "no", SA_OPTION_COMPRESS) ! 445: break; ! 446: case KW_MARK: ! 447: if (!mark_from_string(value, MARK_OP_UNIQUE, &conn->mark_in)) ! 448: { ! 449: cfg->err++; ! 450: break; ! 451: } ! 452: conn->mark_out = conn->mark_in; ! 453: break; ! 454: case KW_MARK_IN: ! 455: if (!mark_from_string(value, MARK_OP_UNIQUE, &conn->mark_in)) ! 456: { ! 457: cfg->err++; ! 458: } ! 459: break; ! 460: case KW_MARK_OUT: ! 461: if (!mark_from_string(value, MARK_OP_UNIQUE, &conn->mark_out)) ! 462: { ! 463: cfg->err++; ! 464: } ! 465: break; ! 466: case KW_TFC: ! 467: if (streq(value, "%mtu")) ! 468: { ! 469: conn->tfc = -1; ! 470: } ! 471: else ! 472: { ! 473: char *endptr; ! 474: ! 475: conn->tfc = strtoul(value, &endptr, 10); ! 476: if (*endptr != '\0') ! 477: { ! 478: DBG1(DBG_APP, "# bad integer value: %s=%s", key, value); ! 479: cfg->err++; ! 480: } ! 481: } ! 482: break; ! 483: case KW_KEYINGTRIES: ! 484: if (streq(value, "%forever")) ! 485: { ! 486: conn->sa_keying_tries = 0; ! 487: } ! 488: else ! 489: { ! 490: char *endptr; ! 491: ! 492: conn->sa_keying_tries = strtoul(value, &endptr, 10); ! 493: if (*endptr != '\0') ! 494: { ! 495: DBG1(DBG_APP, "# bad integer value: %s=%s", key, value); ! 496: cfg->err++; ! 497: } ! 498: } ! 499: break; ! 500: case KW_REKEY: ! 501: KW_SA_OPTION_FLAG("no", "yes", SA_OPTION_DONT_REKEY) ! 502: break; ! 503: case KW_REAUTH: ! 504: KW_SA_OPTION_FLAG("no", "yes", SA_OPTION_DONT_REAUTH) ! 505: break; ! 506: case KW_MOBIKE: ! 507: KW_SA_OPTION_FLAG("yes", "no", SA_OPTION_MOBIKE) ! 508: break; ! 509: case KW_FORCEENCAPS: ! 510: KW_SA_OPTION_FLAG("yes", "no", SA_OPTION_FORCE_ENCAP) ! 511: break; ! 512: case KW_MODECONFIG: ! 513: KW_SA_OPTION_FLAG("push", "pull", SA_OPTION_MODECFG_PUSH) ! 514: break; ! 515: case KW_XAUTH: ! 516: KW_SA_OPTION_FLAG("server", "client", SA_OPTION_XAUTH_SERVER) ! 517: break; ! 518: default: ! 519: break; ! 520: } ! 521: } ! 522: ! 523: /* ! 524: * handles left|rightfirewall and left|rightupdown parameters ! 525: */ ! 526: static void handle_firewall(const char *label, starter_end_t *end, ! 527: starter_config_t *cfg) ! 528: { ! 529: if (end->firewall) ! 530: { ! 531: if (end->updown != NULL) ! 532: { ! 533: DBG1(DBG_APP, "# cannot have both %sfirewall and %supdown", label, ! 534: label); ! 535: cfg->err++; ! 536: } ! 537: else ! 538: { ! 539: end->updown = strdupnull(firewall_defaults); ! 540: end->firewall = FALSE; ! 541: } ! 542: } ! 543: } ! 544: ! 545: /* ! 546: * parse a conn section ! 547: */ ! 548: static void load_conn(starter_conn_t *conn, starter_config_t *cfg, ! 549: conf_parser_t *parser) ! 550: { ! 551: enumerator_t *enumerator; ! 552: dictionary_t *dict; ! 553: const kw_entry_t *entry; ! 554: kw_token_t token; ! 555: char *key, *value; ! 556: ! 557: DBG2(DBG_APP, "Loading conn '%s'", conn->name); ! 558: dict = parser->get_section(parser, CONF_PARSER_CONN, conn->name); ! 559: if (!dict) ! 560: { ! 561: return; ! 562: } ! 563: enumerator = dict->create_enumerator(dict); ! 564: while (enumerator->enumerate(enumerator, &key, &value)) ! 565: { ! 566: bool assigned = FALSE; ! 567: ! 568: entry = in_word_set(key, strlen(key)); ! 569: if (!entry) ! 570: { ! 571: DBG1(DBG_APP, "# unknown keyword '%s'", key); ! 572: cfg->non_fatal_err++; ! 573: continue; ! 574: } ! 575: token = entry->token; ! 576: if (token >= KW_LEFT_FIRST && token <= KW_LEFT_LAST) ! 577: { ! 578: kw_end(conn, &conn->left, token - KW_LEFT_FIRST + KW_END_FIRST, ! 579: key, value, cfg); ! 580: continue; ! 581: } ! 582: else if (token >= KW_RIGHT_FIRST && token <= KW_RIGHT_LAST) ! 583: { ! 584: kw_end(conn, &conn->right, token - KW_RIGHT_FIRST + KW_END_FIRST, ! 585: key, value, cfg); ! 586: continue; ! 587: } ! 588: if (token == KW_AUTO) ! 589: { ! 590: token = KW_CONN_SETUP; ! 591: } ! 592: if (token < KW_CONN_FIRST || token > KW_CONN_LAST) ! 593: { ! 594: DBG1(DBG_APP, "# unsupported keyword '%s' in conn '%s'", ! 595: key, conn->name); ! 596: cfg->err++; ! 597: continue; ! 598: } ! 599: if (is_deprecated(token, key, conn->name)) ! 600: { ! 601: cfg->non_fatal_err++; ! 602: continue; ! 603: } ! 604: if (!assign_arg(token, KW_CONN_FIRST, key, value, conn, ! 605: &assigned)) ! 606: { ! 607: DBG1(DBG_APP, " bad argument value in conn '%s'", conn->name); ! 608: cfg->err++; ! 609: continue; ! 610: } ! 611: if (!assigned) ! 612: { ! 613: handle_keyword(token, conn, key, value, cfg); ! 614: } ! 615: } ! 616: enumerator->destroy(enumerator); ! 617: dict->destroy(dict); ! 618: ! 619: handle_firewall("left", &conn->left, cfg); ! 620: handle_firewall("right", &conn->right, cfg); ! 621: } ! 622: ! 623: /* ! 624: * free the memory used by a starter_ca_t object ! 625: */ ! 626: static void confread_free_ca(starter_ca_t *ca) ! 627: { ! 628: free_args(KW_CA_NAME, KW_CA_LAST, (char *)ca); ! 629: free(ca); ! 630: } ! 631: ! 632: /* ! 633: * free the memory used by a starter_conn_t object ! 634: */ ! 635: static void confread_free_conn(starter_conn_t *conn) ! 636: { ! 637: free_args(KW_END_FIRST, KW_END_LAST, (char *)&conn->left); ! 638: free_args(KW_END_FIRST, KW_END_LAST, (char *)&conn->right); ! 639: free_args(KW_CONN_NAME, KW_CONN_LAST, (char *)conn); ! 640: free(conn); ! 641: } ! 642: ! 643: /* ! 644: * free the memory used by a starter_config_t object ! 645: */ ! 646: void confread_free(starter_config_t *cfg) ! 647: { ! 648: starter_conn_t *conn = cfg->conn_first; ! 649: starter_ca_t *ca = cfg->ca_first; ! 650: ! 651: free_args(KW_SETUP_FIRST, KW_SETUP_LAST, (char *)cfg); ! 652: ! 653: while (conn != NULL) ! 654: { ! 655: starter_conn_t *conn_aux = conn; ! 656: ! 657: conn = conn->next; ! 658: confread_free_conn(conn_aux); ! 659: } ! 660: ! 661: while (ca != NULL) ! 662: { ! 663: starter_ca_t *ca_aux = ca; ! 664: ! 665: ca = ca->next; ! 666: confread_free_ca(ca_aux); ! 667: } ! 668: ! 669: free(cfg); ! 670: } ! 671: ! 672: /* ! 673: * load and parse an IPsec configuration file ! 674: */ ! 675: starter_config_t* confread_load(const char *file) ! 676: { ! 677: conf_parser_t *parser; ! 678: starter_config_t *cfg = NULL; ! 679: enumerator_t *enumerator; ! 680: u_int total_err; ! 681: char *name; ! 682: ! 683: parser = conf_parser_create(file); ! 684: if (!parser->parse(parser)) ! 685: { ! 686: parser->destroy(parser); ! 687: return NULL; ! 688: } ! 689: ! 690: INIT(cfg, ! 691: .setup = { ! 692: .uniqueids = TRUE, ! 693: } ! 694: ); ! 695: ! 696: /* load config setup section */ ! 697: load_setup(cfg, parser); ! 698: ! 699: /* load ca sections */ ! 700: enumerator = parser->get_sections(parser, CONF_PARSER_CA); ! 701: while (enumerator->enumerate(enumerator, &name)) ! 702: { ! 703: u_int previous_err = cfg->err; ! 704: starter_ca_t *ca; ! 705: ! 706: INIT(ca, ! 707: .name = strdup(name), ! 708: ); ! 709: load_ca(ca, cfg, parser); ! 710: ! 711: if (cfg->err > previous_err) ! 712: { ! 713: total_err = cfg->err - previous_err; ! 714: DBG1(DBG_APP, "# ignored ca '%s' due to %d parsing error%s", name, ! 715: total_err, (total_err > 1) ? "s" : ""); ! 716: confread_free_ca(ca); ! 717: cfg->non_fatal_err += cfg->err - previous_err; ! 718: cfg->err = previous_err; ! 719: } ! 720: else ! 721: { ! 722: if (cfg->ca_last) ! 723: { ! 724: cfg->ca_last->next = ca; ! 725: } ! 726: cfg->ca_last = ca; ! 727: if (!cfg->ca_first) ! 728: { ! 729: cfg->ca_first = ca; ! 730: } ! 731: if (ca->startup != STARTUP_NO) ! 732: { ! 733: ca->state = STATE_TO_ADD; ! 734: } ! 735: } ! 736: } ! 737: enumerator->destroy(enumerator); ! 738: ! 739: /* load conn sections */ ! 740: enumerator = parser->get_sections(parser, CONF_PARSER_CONN); ! 741: while (enumerator->enumerate(enumerator, &name)) ! 742: { ! 743: u_int previous_err = cfg->err; ! 744: starter_conn_t *conn; ! 745: ! 746: INIT(conn, ! 747: .name = strdup(name), ! 748: ); ! 749: conn_defaults(conn); ! 750: load_conn(conn, cfg, parser); ! 751: ! 752: if (cfg->err > previous_err) ! 753: { ! 754: total_err = cfg->err - previous_err; ! 755: DBG1(DBG_APP, "# ignored conn '%s' due to %d parsing error%s", name, ! 756: total_err, (total_err > 1) ? "s" : ""); ! 757: confread_free_conn(conn); ! 758: cfg->non_fatal_err += cfg->err - previous_err; ! 759: cfg->err = previous_err; ! 760: } ! 761: else ! 762: { ! 763: if (cfg->conn_last) ! 764: { ! 765: cfg->conn_last->next = conn; ! 766: } ! 767: cfg->conn_last = conn; ! 768: if (!cfg->conn_first) ! 769: { ! 770: cfg->conn_first = conn; ! 771: } ! 772: if (conn->startup != STARTUP_NO) ! 773: { ! 774: conn->state = STATE_TO_ADD; ! 775: } ! 776: } ! 777: } ! 778: enumerator->destroy(enumerator); ! 779: ! 780: parser->destroy(parser); ! 781: ! 782: total_err = cfg->err + cfg->non_fatal_err; ! 783: if (total_err > 0) ! 784: { ! 785: DBG1(DBG_APP, "### %d parsing error%s (%d fatal) ###", ! 786: total_err, (total_err > 1)?"s":"", cfg->err); ! 787: } ! 788: return cfg; ! 789: }