Commit 7bd69ed4 authored by Marek Vavrusa's avatar Marek Vavrusa

Adapting config file parser to server, implemented unit tests.

parent 317feddf
......@@ -37,6 +37,8 @@ src/lib/skip-list.c
src/lib/tree.h
src/lib/bitset.h
src/lib/bitset.c
src/lib/lists.h
src/lib/lists.c
src/dnslib/dname.h
src/dnslib/dname.c
src/dnslib/rrset.h
......@@ -80,6 +82,7 @@ src/alloc/malloc.h
src/alloc/malloc.c
src/alloc/slab.h
src/alloc/slab.c
src/tests/conf_tests.c
src/tests/libtap/tap.c
src/tests/libtap/tap.h
src/tests/main.c
......@@ -102,4 +105,9 @@ src/tests/dnslib/dnslib_zone_tests.c
src/ctl/main.c
src/ctl/process.c
src/ctl/process.h
src/conf/cf-lex.l
src/conf/cf-parse.y
src/conf/conf.c
src/conf/conf.h
src/conf/cutedns.conf.example
tests/querytcp.c
......@@ -9,10 +9,11 @@ COL_CYAN = \033[01;36m
COL_WHITE = \033[01;37m
COL_END = \033[0m
INC_DIRS = obj/ src/ src/hash/ src/dns/ src/other/ src/server/ src/zoneparser/ src/tests src/tests/libtap src/dnslib/ src/stat src/alloc/ src/ctl/ src/lib/
INC_DIRS = obj/ src/ src/hash/ src/dns/ src/other/ src/server/ src/zoneparser/ src/tests src/tests/libtap src/dnslib/ src/stat src/alloc/ src/ctl/ src/lib/ src/conf
SRC_DIRS = src/
TESTS_DIR = src/tests/
ZONEC_DIR = src/zoneparser/
CONF_DIR = src/conf
CTL_DIR = src/ctl
OBJ_DIR = obj/
BIN_DIR = bin/
......@@ -24,7 +25,10 @@ VPATH += ${SRC_DIRS} ${INC_DIRS} ${OBJ_DIR}
PARSER_OBJ = $(OBJ_DIR)zparser
LEXER_OBJ = $(OBJ_DIR)zlexer
CFLEX_OBJ = $(OBJ_DIR)cf-lex
CFPAR_OBJ = $(OBJ_DIR)cf-parse
PARSER_FILES = $(PARSER_OBJ).c $(LEXER_OBJ).c
CONF_FILES = $(CFLEX_OBJ).c $(CFPAR_OBJ).c
TESTS_FILES = $(TESTS_DIR)/main.c $(TESTS_DIR)/libtap/tap.c
ZONEC_FILES = $(ZONEC_DIR)/main.c
CTL_FILES = $(CTL_DIR)/main.c
......@@ -32,7 +36,7 @@ CTL_OBJ = $(OBJ_DIR)log.o $(OBJ_DIR)process.o
SRC_FILES = $(shell find $(SRC_DIRS) ! -path "*/tests/*" -name "*.c" ! -name "main.c")
OBJS = $(PARSER_OBJ).c $(LEXER_OBJ).o $(addprefix $(OBJ_DIR), $(addsuffix .o, $(basename $(notdir $(SRC_FILES)))))
OBJS = $(CFLEX_OBJ).o $(CFPAR_OBJ).o $(PARSER_OBJ).c $(LEXER_OBJ).o $(addprefix $(OBJ_DIR), $(addsuffix .o, $(basename $(notdir $(SRC_FILES)))))
CC = gcc
CFLAGS_DEBUG = -g -O0
......@@ -47,18 +51,26 @@ else
CFLAGS += $(CFLAGS_OPTIMAL)
endif
### Dependencies ###
DEPEND = $(CC) $(addprefix -I ,$(INC_DIRS)) -MM $(SRC_FILES) 2>/dev/null | sed "s%^\([^\ \t\n]*\.o\)%$(OBJ_DIR)/\1%"
# Config lexer/parser
$(CFLEX_OBJ).c: $(CONF_DIR)/cf-lex.l $(CFPAR_OBJ).h
$(LEX) -B -8 -o$(CFLEX_OBJ).c -Pcf_ $(CONF_DIR)/cf-lex.l
Makefile.depend:
@$(DEPEND) > Makefile.depend
$(CFPAR_OBJ).c $(CFPAR_OBJ).h: $(CONF_DIR)/cf-parse.y
$(YACC) -bcf-parse -dv -pcf_ -o $(CFPAR_OBJ).c $(CONF_DIR)/cf-parse.y
# Server lexer/parser
$(LEXER_OBJ).c: $(ZONEC_DIR)/zlexer.lex
$(LEX) -i -t $< >> $@
$(PARSER_OBJ).c $(PARSER_OBJ).h: $(ZONEC_DIR)/zparser.y
$(YACC) -d -o $(PARSER_OBJ).c $(ZONEC_DIR)/zparser.y
### Dependencies ###
DEPEND = $(CC) $(addprefix -I ,$(INC_DIRS)) -MM $(SRC_FILES) 2>/dev/null | sed "s%^\([^\ \t\n]*\.o\)%$(OBJ_DIR)/\1%"
Makefile.depend:
@$(DEPEND) > Makefile.depend
# cutedns
cutedns: Makefile.depend $(PARSER_FILES) $(OBJS) $(SRC_DIRS)main.c
@echo "$(COL_WHITE)Linking... $(COL_YELLOW)${BIN_DIR}$@$(COL_END) <-- $(COL_CYAN)$(OBJS) $(SRC_DIRS)main.c$(COL_END)"
......@@ -96,7 +108,7 @@ $(OBJ_DIR)%.o : %.c
.PHONY: clean doc
clean:
@echo "$(COL_WHITE)Cleaning flex & bison files ...$(COL_RED)"
@rm -vf $(OBJ_DIR)zlexer.c $(OBJ_DIR)zparser.h $(OBJ_DIR)zparser.c
@rm -vf $(OBJ_DIR)/*.h $(OBJ_DIR)/*.c
@echo "$(COL_WHITE)Cleaning object files...$(COL_RED)"
@rm -vf ${OBJ_DIR}/*.o
@echo "$(COL_WHITE)done$(COL_END)"
......
......@@ -5,7 +5,7 @@
#include <stdarg.h>
#include "conf/conf.h"
#include "conf/cf-parse.tab.h"
#include "cf-parse.h"
int (*cf_read_hook)(unsigned char *buf, unsigned int max);
......
......@@ -2,9 +2,9 @@
/* Headers */
#include "conf.h"
static struct conf_iface *this_iface;
static struct conf_key *this_key;
static struct conf_server *this_server;
static conf_iface_t *this_iface;
static conf_key_t *this_key;
static conf_server_t *this_server;
%}
......@@ -34,7 +34,7 @@ conf_entries:
;
interface_start: TEXT {
this_iface = malloc(sizeof(struct conf_iface));
this_iface = malloc(sizeof(conf_iface_t));
this_iface->name = $1;
}
;
......@@ -51,7 +51,7 @@ interfaces:
;
key_start: TEXT {
this_key = malloc(sizeof(struct conf_key));
this_key = malloc(sizeof(conf_key_t));
this_key->name = $1;
}
;
......@@ -68,7 +68,7 @@ keys:
;
server_start: TEXT {
this_server = malloc(sizeof(struct conf_server));
this_server = malloc(sizeof(conf_server_t));
this_server->name = $1;
this_server->key = NULL;
this_server->iface = NULL;
......@@ -80,12 +80,12 @@ server:
| server ADDRESS TEXT ';' { this_server->address = $3; }
| server PORT NUM ';' { this_server->port = $3; }
| server KEY TEXT ';' {
this_server->key = malloc(sizeof(struct conf_key));
this_server->key = malloc(sizeof(conf_key_t));
this_server->key->name = $3;
}
| server INTERFACE TEXT ';' {
this_server->iface = malloc(sizeof(struct conf_iface));
this_server->iface = malloc(sizeof(conf_iface_t));
this_server->iface->name = $3;
}
;
......
......@@ -6,23 +6,30 @@
#include "conf.h"
/* Prevent warnings from -Wmissing-prototypes. */
extern int cf_parse();
static jmp_buf conf_jmpbuf;
config_t *new_config;
struct config *new_config;
struct config *config_alloc(char *name)
config_t *config_new(const char* path)
{
struct config *c = malloc(sizeof(struct config));
c->filename = strdup(name);
config_t *c = malloc(sizeof(config_t));
if (path) {
c->filename = strdup(path);
} else {
c->filename = strdup(CONFIG_DEFAULT_PATH);
}
return c;
}
int config_parse(struct config *c)
int config_parse(config_t *conf)
{
if (setjmp(conf_jmpbuf))
if (setjmp(conf_jmpbuf)) {
return 1;
}
new_config = c;
new_config = conf;
cf_parse();
return 0;
}
......@@ -33,3 +40,11 @@ void cf_error(char *msg)
fputc('\n', stderr);
longjmp(conf_jmpbuf, 1);
}
void config_free(config_t *conf)
{
if (conf) {
free(conf->filename);
free(conf);
}
}
......@@ -18,6 +18,9 @@
#include "lib/lists.h"
/* Constants. */
#define CONFIG_DEFAULT_PATH "/etc/cutedns/cutedns.conf" //!< Default config path
/*!
* \brief Configuration for the interface
*
......@@ -25,7 +28,7 @@
* used in the configuration. Same interface could be used for
* listening and outgoing function.
*/
struct conf_iface {
typedef struct {
node n; /*!< */
/*! \brief Internal name for the interface (not system names). */
......@@ -33,7 +36,7 @@ struct conf_iface {
char *address; /*!< IP (IPv4/v6) address for this interface */
int port; /*!< Port number for this interface */
struct sockaddr *sa; /*!< */
};
} conf_iface_t;
/*!
* \brief List of TSIG algoritms.
......@@ -54,7 +57,7 @@ typedef enum {
/*!
* \brief Configuration for the TSIG key.
*/
struct conf_key {
typedef struct {
node n; /*!< */
char *name; /*!< Name of the key. */
......@@ -65,28 +68,28 @@ struct conf_key {
*/
tsig_alg_t algorithm;
char *secret; /*!< Key data. */
};
} conf_key_t;
/*!
* \brief Remote server for XFR/NOTIFY.
*
* \todo Long description.
*/
struct conf_server {
typedef struct {
node n;
char *name; /*!< Name of the server in the configuration. */
char *address; /*!< Hostname or IP address of the server. */
int port; /*!< Remote port. */
/*! \brief TSIG key used to authenticate messages from/to server. */
struct conf_key *key;
conf_key_t *key;
/*!
* \brief Interface to use to communicate with the server (including
* outgoing IP address).
*/
struct conf_iface *iface;
};
conf_iface_t *iface;
} conf_server_t;
/*!
* \todo Import from dns library.
......@@ -107,10 +110,10 @@ typedef enum {
*
* \todo Missing XFR type (AXFR/IXFR/IXFR-ONLY) for each server.
*/
struct conf_zone {
typedef struct {
node n; /*!< */
char *name; /*!< Zone name. */
conf_class_t class; /*!< Zone class (IN or CH). */
conf_class_t cls; /*!< Zone class (IN or CH). */
/*! \todo Generic storage, now just a filename on the disk. */
char *storage;
......@@ -123,26 +126,27 @@ struct conf_zone {
/*! \brief List of DNS servers to be notified on zone change. */
list notify_out;
};
} conf_zone_t;
/*!
* \brief Maps internal category to the (sys)log facility.
*
* \todo ref #1
*/
struct conf_log_map {
typedef struct {
node n;
int facility; /*!< (Sys)log facility, see man 3 syslog. */
int category; /*!< Internal log category. */
};
} conf_log_map_t;
/*!
* \brief Types of log output.
*/
typedef enum {
LOG_SYSLOG, /*!< Logging to standard syslog(3). */
LOG_STDERR, /*!< Print error messages on the stderr. */
LOG_FILE /*!< Generic logging to (unbuffered) file on the disk. */
// LOG_SYSLOG, /*!< Logging to standard syslog(3). */
// LOG_STDERR, /*!< Print error messages on the stderr. */
// LOG_FILE /*!< Generic logging to (unbuffered) file on the disk. */
ABCD
} log_type_t;
/*!
......@@ -150,12 +154,12 @@ typedef enum {
*
* \todo Give it some more thought (ref #1).
*/
struct conf_log {
typedef struct {
node n; /*!< */
log_type_t log_type; /*!< Type of the log (SYSLOG/STDERR/FILE). */
char *log_output; /*!< Filename in case of LOG_FILE, else NULL. */
list log_map; /*!< What type of messages to log. */
};
} conf_log_t;
/*!
* \brief Main config structure.
......@@ -164,7 +168,7 @@ struct conf_log {
*
* \todo More documentation.
*/
struct config {
typedef struct {
char *filename; /*!< Name of the config file. */
char *identity; /*!< Identity to return on CH TXT id.server. */
......@@ -179,15 +183,16 @@ struct config {
list keys; /*!< List of TSIG keys. */
list servers; /*!< List of remote servers. */
list zones; /*!< List of zones. */
};
} config_t;
extern struct config *new_config;
extern config_t *new_config;
extern int (*cf_read_hook)(unsigned char *buf, unsigned int max);
struct config *config_alloc();
int config_parse(struct config *);
void config_free(struct config *);
/* Specific configuration API. */
config_t *config_new(const char* path);
int config_parse(config_t *conf);
void config_free(config_t *conf);
#endif /* _CUTEDNS_CONF_H_ */
......
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "conf.h"
static int conf_fd;
static char *config_name = "cutedns.conf";
static int cf_read(unsigned char *dest, unsigned int len)
{
int l = read(conf_fd, dest, len);
if (l < 0) {
cf_error("Read error");
}
return l;
}
int main(int argc, void **argv)
{
int ret;
char *name = config_name;
struct config *conf = config_alloc(name);
conf_fd = open(name, O_RDONLY);
if (conf_fd < 0) {
return 1;
}
cf_read_hook = cf_read;
ret = config_parse(conf);
close(conf_fd);
return ret;
}
......@@ -54,6 +54,7 @@ void add_tail_list(list *, list *);
void init_list(list *);
void insert_node(node *, node *);
/*! \todo This is broken atm.
#ifndef _BIRD_LISTS_C_
#define LIST_INLINE extern inline
#include "lib/lists.c"
......@@ -61,5 +62,7 @@ void insert_node(node *, node *);
#else
#define LIST_INLINE
#endif
*/
#define LIST_INLINE
#endif
......@@ -6,6 +6,7 @@
#include "server.h"
#include "zoneparser.h"
#include "process.h"
#include "conf/conf.h"
/*----------------------------------------------------------------------------*/
......@@ -43,10 +44,11 @@ void help(int argc, char **argv)
printf("Usage: %s [parameters] [<filename1> <filename2> ...]\n",
argv[0]);
printf("Parameters:\n"
" -d\tRun server as a daemon.\n"
" -v\tVerbose mode - additional runtime information.\n"
" -V\tPrint version of the server.\n"
" -h\tPrint help and usage.\n");
" -c [file] Select configuration file.\n"
" -d Run server as a daemon.\n"
" -v Verbose mode - additional runtime information.\n"
" -V Print version of the server.\n"
" -h Print help and usage.\n");
}
int main(int argc, char **argv)
......@@ -55,9 +57,13 @@ int main(int argc, char **argv)
int c = 0;
int verbose = 0;
int daemonize = 0;
while ((c = getopt (argc, argv, "dvVh")) != -1) {
const char* config_fn = 0;
while ((c = getopt (argc, argv, "c:dvVh")) != -1) {
switch (c)
{
case 'c':
config_fn = optarg;
break;
case 'd':
daemonize = 1;
break;
......@@ -88,6 +94,16 @@ int main(int argc, char **argv)
}
}
// Open configuration
config_t* conf = config_new(config_fn);
if (config_parse(conf) != 0) {
config_free(conf);
log_open(0, LOG_MASK(LOG_ERR));
log_error("Opening config file %s failed...\n", config_fn);
log_close();
return 1;
}
// Open log
int log_mask = LOG_MASK(LOG_ERR) | LOG_MASK(LOG_WARNING);
int print_mask = LOG_MASK(LOG_ERR) | LOG_MASK(LOG_WARNING);
......
#include <stdio.h>
#include "tap_unit.h"
#include "conf/conf.h"
static FILE* conf_fp = 0;
static int conf_tests_count(int argc, char *argv[]);
static int conf_tests_run(int argc, char *argv[]);
/*! Exported unit API.
*/
unit_api conf_tests_api = {
"Configuration parser", //! Unit name
&conf_tests_count, //! Count scheduled tests
&conf_tests_run //! Run scheduled tests
};
/*! This helper routine should report number of
* scheduled tests for given parameters.
*/
static int conf_tests_count(int argc, char *argv[])
{
return 3;
}
static int cf_read(unsigned char *dest, unsigned int len)
{
return fread(dest, len, 1, conf_fp);
}
/*! Run all scheduled tests for given parameters.
*/
static int conf_tests_run(int argc, char *argv[])
{
// Test 1: Open configuration file for reading
char *name = "";
conf_fp = fopen(name, "r");
ok(conf_fp != 0, "open configuration file %s", name);
if (conf_fp == 0) {
return 1;
}
// Test 2: Allocate new config
config_t *conf = config_new(name);
ok(conf != 0, "config_new()");
cf_read_hook = cf_read;
// Test 3: Parse config
int ret = config_parse(conf);
ok(ret == 0, "parsing configuration file %s", name);
// Deallocating config
config_free(conf);
fclose(conf_fp);
conf_fp = 0;
return 0;
}
......@@ -10,6 +10,7 @@
#include "dnslib_tests.c"
#include "server_tests.c"
#include "slab_tests.c"
#include "conf_tests.c"
// Run all loaded units
int main(int argc, char *argv[])
......@@ -19,14 +20,15 @@ int main(int argc, char *argv[])
// Build test set
unit_api *tests[] = {
&skiplist_tests_api, //! Skip list unit
&dthreads_tests_api, //! DThreads testing unit
&da_tests_api, //! Dynamic array unit
&cuckoo_tests_api, //! Cuckoo hashing unit
&zonedb_tests_api, //! Zone database unit
&dnslib_tests_api, //! DNS library unit
&server_tests_api, //! Server unit
&slab_tests_api, //! SLAB allocator unit
&skiplist_tests_api, //! Skip list unit
&dthreads_tests_api, //! DThreads testing unit
&da_tests_api, //! Dynamic array unit
&cuckoo_tests_api, //! Cuckoo hashing unit
&zonedb_tests_api, //! Zone database unit
&conf_tests_api, //! Configuration parser tests
&dnslib_tests_api, //! DNS library unit
&server_tests_api, //! Server unit
&slab_tests_api, //! SLAB allocator unit
NULL
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment