summaryrefslogtreecommitdiffstats
path: root/contrib/openbsm/bin/auditdistd/parse.y
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/openbsm/bin/auditdistd/parse.y')
-rw-r--r--contrib/openbsm/bin/auditdistd/parse.y856
1 files changed, 856 insertions, 0 deletions
diff --git a/contrib/openbsm/bin/auditdistd/parse.y b/contrib/openbsm/bin/auditdistd/parse.y
new file mode 100644
index 0000000..fbe1000
--- /dev/null
+++ b/contrib/openbsm/bin/auditdistd/parse.y
@@ -0,0 +1,856 @@
+%{
+/*-
+ * Copyright (c) 2012 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $P4: //depot/projects/trustedbsd/openbsm/bin/auditdistd/parse.y#5 $
+ */
+
+#include <config/config.h>
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/sysctl.h>
+
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+#ifndef HAVE_STRLCPY
+#include <compat/strlcpy.h>
+#endif
+
+#include "auditdistd.h"
+#include "pjdlog.h"
+
+extern int depth;
+extern int lineno;
+
+extern FILE *yyin;
+extern char *yytext;
+
+static struct adist_config *lconfig;
+static struct adist_host *curhost;
+#define SECTION_GLOBAL 0
+#define SECTION_SENDER 1
+#define SECTION_RECEIVER 2
+static int cursection;
+
+/* Sender section. */
+static char depth1_source[ADIST_ADDRSIZE];
+static int depth1_checksum;
+static int depth1_compression;
+/* Sender and receiver sections. */
+static char depth1_directory[PATH_MAX];
+
+static bool adjust_directory(char *path);
+static bool family_supported(int family);
+
+extern void yyrestart(FILE *);
+%}
+
+%token CB
+%token CERTFILE
+%token DIRECTORY
+%token FINGERPRINT
+%token HOST
+%token KEYFILE
+%token LISTEN
+%token NAME
+%token OB
+%token PASSWORD
+%token PIDFILE
+%token RECEIVER REMOTE
+%token SENDER SOURCE
+%token TIMEOUT
+
+/*
+%type <num> checksum_type
+%type <num> compression_type
+*/
+
+%union
+{
+ int num;
+ char *str;
+}
+
+%token <num> NUM
+%token <str> STR
+
+%%
+
+statements:
+ |
+ statements statement
+ ;
+
+statement:
+ name_statement
+ |
+ pidfile_statement
+ |
+ timeout_statement
+ |
+ sender_statement
+ |
+ receiver_statement
+ ;
+
+name_statement: NAME STR
+ {
+ PJDLOG_RASSERT(depth == 0,
+ "The name variable can only be specificed in the global section.");
+
+ if (lconfig->adc_name[0] != '\0') {
+ pjdlog_error("The name variable is specified twice.");
+ free($2);
+ return (1);
+ }
+ if (strlcpy(lconfig->adc_name, $2,
+ sizeof(lconfig->adc_name)) >=
+ sizeof(lconfig->adc_name)) {
+ pjdlog_error("The name value is too long.");
+ free($2);
+ return (1);
+ }
+ free($2);
+ }
+ ;
+
+pidfile_statement: PIDFILE STR
+ {
+ PJDLOG_RASSERT(depth == 0,
+ "The pidfile variable can only be specificed in the global section.");
+
+ if (lconfig->adc_pidfile[0] != '\0') {
+ pjdlog_error("The pidfile variable is specified twice.");
+ free($2);
+ return (1);
+ }
+ if (strcmp($2, "none") != 0 && $2[0] != '/') {
+ pjdlog_error("The pidfile variable must be set to absolute pathname or \"none\".");
+ free($2);
+ return (1);
+ }
+ if (strlcpy(lconfig->adc_pidfile, $2,
+ sizeof(lconfig->adc_pidfile)) >=
+ sizeof(lconfig->adc_pidfile)) {
+ pjdlog_error("The pidfile value is too long.");
+ free($2);
+ return (1);
+ }
+ free($2);
+ }
+ ;
+
+timeout_statement: TIMEOUT NUM
+ {
+ PJDLOG_ASSERT(depth == 0);
+
+ lconfig->adc_timeout = $2;
+ }
+ ;
+
+sender_statement: SENDER sender_start sender_entries CB
+ {
+ PJDLOG_ASSERT(depth == 0);
+ PJDLOG_ASSERT(cursection == SECTION_SENDER);
+
+ /* Configure defaults. */
+ if (depth1_checksum == -1)
+ depth1_checksum = ADIST_CHECKSUM_NONE;
+ if (depth1_compression == -1)
+ depth1_compression = ADIST_COMPRESSION_NONE;
+ if (depth1_directory[0] == '\0') {
+ (void)strlcpy(depth1_directory, ADIST_DIRECTORY_SENDER,
+ sizeof(depth1_directory));
+ }
+ /* Empty depth1_source is ok. */
+ TAILQ_FOREACH(curhost, &lconfig->adc_hosts, adh_next) {
+ if (curhost->adh_role != ADIST_ROLE_SENDER)
+ continue;
+ if (curhost->adh_checksum == -1)
+ curhost->adh_checksum = depth1_checksum;
+ if (curhost->adh_compression == -1)
+ curhost->adh_compression = depth1_compression;
+ if (curhost->adh_directory[0] == '\0') {
+ (void)strlcpy(curhost->adh_directory,
+ depth1_directory,
+ sizeof(curhost->adh_directory));
+ }
+ if (curhost->adh_localaddr[0] == '\0') {
+ (void)strlcpy(curhost->adh_localaddr,
+ depth1_source,
+ sizeof(curhost->adh_localaddr));
+ }
+ }
+ cursection = SECTION_GLOBAL;
+ }
+ ;
+
+sender_start: OB
+ {
+ PJDLOG_ASSERT(depth == 1);
+ PJDLOG_ASSERT(cursection == SECTION_GLOBAL);
+
+ cursection = SECTION_SENDER;
+ depth1_checksum = -1;
+ depth1_compression = -1;
+ depth1_source[0] = '\0';
+ depth1_directory[0] = '\0';
+
+#ifndef HAVE_AUDIT_SYSCALLS
+ pjdlog_error("Sender functionality is not available.");
+ return (1);
+#endif
+ }
+ ;
+
+sender_entries:
+ |
+ sender_entries sender_entry
+ ;
+
+sender_entry:
+ source_statement
+ |
+ directory_statement
+/*
+ |
+ checksum_statement
+ |
+ compression_statement
+*/
+ |
+ sender_host_statement
+ ;
+
+receiver_statement: RECEIVER receiver_start receiver_entries CB
+ {
+ PJDLOG_ASSERT(depth == 0);
+ PJDLOG_ASSERT(cursection == SECTION_RECEIVER);
+
+ /*
+ * If not listen addresses were specified,
+ * configure default ones.
+ */
+ if (TAILQ_EMPTY(&lconfig->adc_listen)) {
+ struct adist_listen *lst;
+
+ if (family_supported(AF_INET)) {
+ lst = calloc(1, sizeof(*lst));
+ if (lst == NULL) {
+ pjdlog_error("Unable to allocate memory for listen address.");
+ return (1);
+ }
+ (void)strlcpy(lst->adl_addr,
+ ADIST_LISTEN_TLS_TCP4,
+ sizeof(lst->adl_addr));
+ TAILQ_INSERT_TAIL(&lconfig->adc_listen, lst, adl_next);
+ } else {
+ pjdlog_debug(1,
+ "No IPv4 support in the kernel, not listening on IPv4 address.");
+ }
+ if (family_supported(AF_INET6)) {
+ lst = calloc(1, sizeof(*lst));
+ if (lst == NULL) {
+ pjdlog_error("Unable to allocate memory for listen address.");
+ return (1);
+ }
+ (void)strlcpy(lst->adl_addr,
+ ADIST_LISTEN_TLS_TCP6,
+ sizeof(lst->adl_addr));
+ TAILQ_INSERT_TAIL(&lconfig->adc_listen, lst, adl_next);
+ } else {
+ pjdlog_debug(1,
+ "No IPv6 support in the kernel, not listening on IPv6 address.");
+ }
+ if (TAILQ_EMPTY(&lconfig->adc_listen)) {
+ pjdlog_error("No address to listen on.");
+ return (1);
+ }
+ }
+ /* Configure defaults. */
+ if (depth1_directory[0] == '\0') {
+ (void)strlcpy(depth1_directory,
+ ADIST_DIRECTORY_RECEIVER,
+ sizeof(depth1_directory));
+ }
+ TAILQ_FOREACH(curhost, &lconfig->adc_hosts, adh_next) {
+ if (curhost->adh_role != ADIST_ROLE_RECEIVER)
+ continue;
+ if (curhost->adh_directory[0] == '\0') {
+ if (snprintf(curhost->adh_directory,
+ sizeof(curhost->adh_directory), "%s/%s",
+ depth1_directory, curhost->adh_name) >=
+ (ssize_t)sizeof(curhost->adh_directory)) {
+ pjdlog_error("Directory value is too long.");
+ return (1);
+ }
+ }
+ }
+ cursection = SECTION_GLOBAL;
+ }
+ ;
+
+receiver_start: OB
+ {
+ PJDLOG_ASSERT(depth == 1);
+ PJDLOG_ASSERT(cursection == SECTION_GLOBAL);
+
+ cursection = SECTION_RECEIVER;
+ depth1_directory[0] = '\0';
+ }
+ ;
+
+receiver_entries:
+ |
+ receiver_entries receiver_entry
+ ;
+
+receiver_entry:
+ listen_statement
+ |
+ directory_statement
+ |
+ certfile_statement
+ |
+ keyfile_statement
+ |
+ receiver_host_statement
+ ;
+
+/*
+checksum_statement: CHECKSUM checksum_type
+ {
+ PJDLOG_ASSERT(cursection == SECTION_SENDER);
+
+ switch (depth) {
+ case 1:
+ depth1_checksum = $2;
+ break;
+ case 2:
+ PJDLOG_ASSERT(curhost != NULL);
+ curhost->adh_checksum = $2;
+ break;
+ default:
+ PJDLOG_ABORT("checksum at wrong depth level");
+ }
+ }
+ ;
+
+checksum_type:
+ NONE { $$ = ADIST_CHECKSUM_NONE; }
+ |
+ CRC32 { $$ = ADIST_CHECKSUM_CRC32; }
+ |
+ SHA256 { $$ = ADIST_CHECKSUM_SHA256; }
+ ;
+
+compression_statement: COMPRESSION compression_type
+ {
+ PJDLOG_ASSERT(cursection == SECTION_SENDER);
+
+ switch (depth) {
+ case 1:
+ depth1_compression = $2;
+ break;
+ case 2:
+ PJDLOG_ASSERT(curhost != NULL);
+ curhost->adh_compression = $2;
+ break;
+ default:
+ PJDLOG_ABORT("compression at wrong depth level");
+ }
+ }
+ ;
+
+compression_type:
+ NONE { $$ = ADIST_COMPRESSION_NONE; }
+ |
+ LZF { $$ = ADIST_COMPRESSION_LZF; }
+ ;
+*/
+
+directory_statement: DIRECTORY STR
+ {
+ PJDLOG_ASSERT(cursection == SECTION_SENDER ||
+ cursection == SECTION_RECEIVER);
+
+ switch (depth) {
+ case 1:
+ if (strlcpy(depth1_directory, $2,
+ sizeof(depth1_directory)) >=
+ sizeof(depth1_directory)) {
+ pjdlog_error("Directory value is too long.");
+ free($2);
+ return (1);
+ }
+ if (!adjust_directory(depth1_directory))
+ return (1);
+ break;
+ case 2:
+ if (cursection == SECTION_SENDER || $2[0] == '/') {
+ if (strlcpy(curhost->adh_directory, $2,
+ sizeof(curhost->adh_directory)) >=
+ sizeof(curhost->adh_directory)) {
+ pjdlog_error("Directory value is too long.");
+ free($2);
+ return (1);
+ }
+ } else /* if (cursection == SECTION_RECEIVER) */ {
+ if (depth1_directory[0] == '\0') {
+ pjdlog_error("Directory path must be absolute.");
+ free($2);
+ return (1);
+ }
+ if (snprintf(curhost->adh_directory,
+ sizeof(curhost->adh_directory), "%s/%s",
+ depth1_directory, $2) >=
+ (ssize_t)sizeof(curhost->adh_directory)) {
+ pjdlog_error("Directory value is too long.");
+ free($2);
+ return (1);
+ }
+ }
+ break;
+ default:
+ PJDLOG_ABORT("directory at wrong depth level");
+ }
+ free($2);
+ }
+ ;
+
+source_statement: SOURCE STR
+ {
+ PJDLOG_RASSERT(cursection == SECTION_SENDER,
+ "The source variable must be in sender section.");
+
+ switch (depth) {
+ case 1:
+ if (strlcpy(depth1_source, $2,
+ sizeof(depth1_source)) >=
+ sizeof(depth1_source)) {
+ pjdlog_error("Source value is too long.");
+ free($2);
+ return (1);
+ }
+ break;
+ case 2:
+ if (strlcpy(curhost->adh_localaddr, $2,
+ sizeof(curhost->adh_localaddr)) >=
+ sizeof(curhost->adh_localaddr)) {
+ pjdlog_error("Source value is too long.");
+ free($2);
+ return (1);
+ }
+ break;
+ }
+ free($2);
+ }
+ ;
+
+fingerprint_statement: FINGERPRINT STR
+ {
+ PJDLOG_ASSERT(cursection == SECTION_SENDER);
+ PJDLOG_ASSERT(depth == 2);
+
+ if (strncasecmp($2, "SHA256=", 7) != 0) {
+ pjdlog_error("Invalid fingerprint value.");
+ free($2);
+ return (1);
+ }
+ if (strlcpy(curhost->adh_fingerprint, $2,
+ sizeof(curhost->adh_fingerprint)) >=
+ sizeof(curhost->adh_fingerprint)) {
+ pjdlog_error("Fingerprint value is too long.");
+ free($2);
+ return (1);
+ }
+ free($2);
+ }
+ ;
+
+password_statement: PASSWORD STR
+ {
+ PJDLOG_ASSERT(cursection == SECTION_SENDER ||
+ cursection == SECTION_RECEIVER);
+ PJDLOG_ASSERT(depth == 2);
+
+ if (strlcpy(curhost->adh_password, $2,
+ sizeof(curhost->adh_password)) >=
+ sizeof(curhost->adh_password)) {
+ pjdlog_error("Password value is too long.");
+ bzero($2, strlen($2));
+ free($2);
+ return (1);
+ }
+ bzero($2, strlen($2));
+ free($2);
+ }
+ ;
+
+certfile_statement: CERTFILE STR
+ {
+ PJDLOG_ASSERT(cursection == SECTION_RECEIVER);
+ PJDLOG_ASSERT(depth == 1);
+
+ if (strlcpy(lconfig->adc_certfile, $2,
+ sizeof(lconfig->adc_certfile)) >=
+ sizeof(lconfig->adc_certfile)) {
+ pjdlog_error("Certfile value is too long.");
+ free($2);
+ return (1);
+ }
+ free($2);
+ }
+ ;
+
+keyfile_statement: KEYFILE STR
+ {
+ PJDLOG_ASSERT(cursection == SECTION_RECEIVER);
+ PJDLOG_ASSERT(depth == 1);
+
+ if (strlcpy(lconfig->adc_keyfile, $2,
+ sizeof(lconfig->adc_keyfile)) >=
+ sizeof(lconfig->adc_keyfile)) {
+ pjdlog_error("Keyfile value is too long.");
+ free($2);
+ return (1);
+ }
+ free($2);
+ }
+ ;
+
+listen_statement: LISTEN STR
+ {
+ struct adist_listen *lst;
+
+ PJDLOG_ASSERT(depth == 1);
+ PJDLOG_ASSERT(cursection == SECTION_RECEIVER);
+
+ lst = calloc(1, sizeof(*lst));
+ if (lst == NULL) {
+ pjdlog_error("Unable to allocate memory for listen address.");
+ free($2);
+ return (1);
+ }
+ if (strlcpy(lst->adl_addr, $2, sizeof(lst->adl_addr)) >=
+ sizeof(lst->adl_addr)) {
+ pjdlog_error("listen argument is too long.");
+ free($2);
+ free(lst);
+ return (1);
+ }
+ TAILQ_INSERT_TAIL(&lconfig->adc_listen, lst, adl_next);
+ free($2);
+ }
+ ;
+
+sender_host_statement: HOST host_start OB sender_host_entries CB
+ {
+ /* Put it onto host list. */
+ TAILQ_INSERT_TAIL(&lconfig->adc_hosts, curhost, adh_next);
+ curhost = NULL;
+ }
+ ;
+
+receiver_host_statement: HOST host_start OB receiver_host_entries CB
+ {
+ /* Put it onto host list. */
+ TAILQ_INSERT_TAIL(&lconfig->adc_hosts, curhost, adh_next);
+ curhost = NULL;
+ }
+ ;
+
+host_start: STR
+ {
+ /* Check if there is no duplicate entry. */
+ TAILQ_FOREACH(curhost, &lconfig->adc_hosts, adh_next) {
+ if (strcmp(curhost->adh_name, $1) != 0)
+ continue;
+ if (curhost->adh_role == ADIST_ROLE_SENDER &&
+ cursection == SECTION_RECEIVER) {
+ continue;
+ }
+ if (curhost->adh_role == ADIST_ROLE_RECEIVER &&
+ cursection == SECTION_SENDER) {
+ continue;
+ }
+ pjdlog_error("%s host %s is configured more than once.",
+ curhost->adh_role == ADIST_ROLE_SENDER ?
+ "Sender" : "Receiver", curhost->adh_name);
+ free($1);
+ return (1);
+ }
+
+ curhost = calloc(1, sizeof(*curhost));
+ if (curhost == NULL) {
+ pjdlog_error("Unable to allocate memory for host configuration.");
+ free($1);
+ return (1);
+ }
+ if (strlcpy(curhost->adh_name, $1, sizeof(curhost->adh_name)) >=
+ sizeof(curhost->adh_name)) {
+ pjdlog_error("Host name is too long.");
+ free($1);
+ return (1);
+ }
+ free($1);
+ curhost->adh_role = cursection == SECTION_SENDER ?
+ ADIST_ROLE_SENDER : ADIST_ROLE_RECEIVER;
+ curhost->adh_version = ADIST_VERSION;
+ curhost->adh_localaddr[0] = '\0';
+ curhost->adh_remoteaddr[0] = '\0';
+ curhost->adh_remote = NULL;
+ curhost->adh_directory[0] = '\0';
+ curhost->adh_password[0] = '\0';
+ curhost->adh_fingerprint[0] = '\0';
+ curhost->adh_worker_pid = 0;
+ curhost->adh_conn = NULL;
+ }
+ ;
+
+sender_host_entries:
+ |
+ sender_host_entries sender_host_entry
+ ;
+
+sender_host_entry:
+ source_statement
+ |
+ remote_statement
+ |
+ directory_statement
+ |
+ fingerprint_statement
+ |
+ password_statement
+/*
+ |
+ checksum_statement
+ |
+ compression_statement
+*/
+ ;
+
+receiver_host_entries:
+ |
+ receiver_host_entries receiver_host_entry
+ ;
+
+receiver_host_entry:
+ remote_statement
+ |
+ directory_statement
+ |
+ password_statement
+ ;
+
+remote_statement: REMOTE STR
+ {
+ PJDLOG_ASSERT(depth == 2);
+ PJDLOG_ASSERT(cursection == SECTION_SENDER ||
+ cursection == SECTION_RECEIVER);
+
+ if (strlcpy(curhost->adh_remoteaddr, $2,
+ sizeof(curhost->adh_remoteaddr)) >=
+ sizeof(curhost->adh_remoteaddr)) {
+ pjdlog_error("Remote value is too long.");
+ free($2);
+ return (1);
+ }
+ free($2);
+ }
+ ;
+
+%%
+
+static bool
+family_supported(int family)
+{
+ int sock;
+
+ sock = socket(family, SOCK_STREAM, 0);
+ if (sock == -1 && errno == EPROTONOSUPPORT)
+ return (false);
+ if (sock >= 0)
+ (void)close(sock);
+ return (true);
+}
+
+static bool
+adjust_directory(char *path)
+{
+ size_t len;
+
+ len = strlen(path);
+ for (;;) {
+ if (len == 0) {
+ pjdlog_error("Directory path is empty.");
+ return (false);
+ }
+ if (path[len - 1] != '/')
+ break;
+ len--;
+ path[len] = '\0';
+ }
+ if (path[0] != '/') {
+ pjdlog_error("Directory path must be absolute.");
+ return (false);
+ }
+ return (true);
+}
+
+static int
+my_name(char *name, size_t size)
+{
+ char buf[MAXHOSTNAMELEN];
+ char *pos;
+
+ if (gethostname(buf, sizeof(buf)) < 0) {
+ pjdlog_errno(LOG_ERR, "gethostname() failed");
+ return (-1);
+ }
+
+ /* First component of the host name. */
+ pos = strchr(buf, '.');
+ if (pos == NULL)
+ (void)strlcpy(name, buf, size);
+ else
+ (void)strlcpy(name, buf, MIN((size_t)(pos - buf + 1), size));
+
+ if (name[0] == '\0') {
+ pjdlog_error("Empty host name.");
+ return (-1);
+ }
+
+ return (0);
+}
+
+void
+yyerror(const char *str)
+{
+
+ pjdlog_error("Unable to parse configuration file at line %d near '%s': %s",
+ lineno, yytext, str);
+}
+
+struct adist_config *
+yy_config_parse(const char *config, bool exitonerror)
+{
+ int ret;
+
+ curhost = NULL;
+ cursection = SECTION_GLOBAL;
+ depth = 0;
+ lineno = 0;
+
+ lconfig = calloc(1, sizeof(*lconfig));
+ if (lconfig == NULL) {
+ pjdlog_error("Unable to allocate memory for configuration.");
+ if (exitonerror)
+ exit(EX_TEMPFAIL);
+ return (NULL);
+ }
+ TAILQ_INIT(&lconfig->adc_hosts);
+ TAILQ_INIT(&lconfig->adc_listen);
+ lconfig->adc_name[0] = '\0';
+ lconfig->adc_timeout = -1;
+ lconfig->adc_pidfile[0] = '\0';
+ lconfig->adc_certfile[0] = '\0';
+ lconfig->adc_keyfile[0] = '\0';
+
+ yyin = fopen(config, "r");
+ if (yyin == NULL) {
+ pjdlog_errno(LOG_ERR, "Unable to open configuration file %s",
+ config);
+ yy_config_free(lconfig);
+ if (exitonerror)
+ exit(EX_OSFILE);
+ return (NULL);
+ }
+ yyrestart(yyin);
+ ret = yyparse();
+ fclose(yyin);
+ if (ret != 0) {
+ yy_config_free(lconfig);
+ if (exitonerror)
+ exit(EX_CONFIG);
+ return (NULL);
+ }
+
+ /*
+ * Let's see if everything is set up.
+ */
+ if (lconfig->adc_name[0] == '\0' && my_name(lconfig->adc_name,
+ sizeof(lconfig->adc_name)) == -1) {
+ yy_config_free(lconfig);
+ if (exitonerror)
+ exit(EX_CONFIG);
+ return (NULL);
+ }
+ if (lconfig->adc_timeout == -1)
+ lconfig->adc_timeout = ADIST_TIMEOUT;
+ if (lconfig->adc_pidfile[0] == '\0') {
+ (void)strlcpy(lconfig->adc_pidfile, ADIST_PIDFILE,
+ sizeof(lconfig->adc_pidfile));
+ }
+ if (lconfig->adc_certfile[0] == '\0') {
+ (void)strlcpy(lconfig->adc_certfile, ADIST_CERTFILE,
+ sizeof(lconfig->adc_certfile));
+ }
+ if (lconfig->adc_keyfile[0] == '\0') {
+ (void)strlcpy(lconfig->adc_keyfile, ADIST_KEYFILE,
+ sizeof(lconfig->adc_keyfile));
+ }
+
+ return (lconfig);
+}
+
+void
+yy_config_free(struct adist_config *config)
+{
+ struct adist_host *adhost;
+ struct adist_listen *lst;
+
+ while ((lst = TAILQ_FIRST(&config->adc_listen)) != NULL) {
+ TAILQ_REMOVE(&config->adc_listen, lst, adl_next);
+ free(lst);
+ }
+ while ((adhost = TAILQ_FIRST(&config->adc_hosts)) != NULL) {
+ TAILQ_REMOVE(&config->adc_hosts, adhost, adh_next);
+ bzero(adhost, sizeof(*adhost));
+ free(adhost);
+ }
+ free(config);
+}
OpenPOWER on IntegriCloud