mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 17:51:53 +00:00
94eb0858c2
There is a simple universal IO loop, taking care of events, timers and sockets. Primarily, one instance of a protocol should use exactly one IO loop to do all its work, as is now done in BFD. Contrary to previous versions, the loop is now launched and cleaned by the nest/proto.c code, allowing for a protocol to just request its own loop by setting the loop's lock order in config higher than the_bird. It is not supported nor checked if any protocol changed the requested lock order in reconfigure. No protocol should do it at all.
230 lines
4.7 KiB
C
230 lines
4.7 KiB
C
/*
|
|
* BIRD Test -- Utils for testing parsing configuration file
|
|
*
|
|
* (c) 2015 CZ.NIC z.s.p.o.
|
|
*
|
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
|
|
#include "test/birdtest.h"
|
|
#include "test/bt-utils.h"
|
|
|
|
#include "nest/bird.h"
|
|
#include "nest/route.h"
|
|
#include "nest/protocol.h"
|
|
|
|
#include "sysdep/unix/unix.h"
|
|
#include "sysdep/unix/krt.h"
|
|
|
|
#include "nest/iface.h"
|
|
#include "nest/locks.h"
|
|
|
|
#include "filter/filter.h"
|
|
|
|
#define BETWEEN(a, b, c) (((a) >= (b)) && ((a) <= (c)))
|
|
|
|
static const byte *bt_config_parse_pos;
|
|
static uint bt_config_parse_remain_len;
|
|
|
|
/* This is cf_read_hook for hard-coded text configuration */
|
|
static int
|
|
cf_static_read(byte *dest, uint max_len, int fd UNUSED)
|
|
{
|
|
if (max_len > bt_config_parse_remain_len)
|
|
max_len = bt_config_parse_remain_len;
|
|
memcpy(dest, bt_config_parse_pos, max_len);
|
|
bt_config_parse_pos += max_len;
|
|
bt_config_parse_remain_len -= max_len;
|
|
return max_len;
|
|
}
|
|
|
|
/* This is cf_read_hook for reading configuration files,
|
|
* function is copied from main.c, cf_read() */
|
|
static int
|
|
cf_file_read(byte *dest, uint max_len, int fd)
|
|
{
|
|
int l = read(fd, dest, max_len);
|
|
if (l < 0)
|
|
cf_error("Read error");
|
|
return l;
|
|
}
|
|
|
|
void resource_sys_init(void);
|
|
|
|
void
|
|
bt_bird_init(void)
|
|
{
|
|
resource_sys_init();
|
|
if(bt_verbose)
|
|
log_init_debug("");
|
|
log_switch(bt_verbose != 0, NULL, NULL);
|
|
|
|
the_bird_lock();
|
|
resource_init();
|
|
olock_init();
|
|
birdloop_init();
|
|
io_init();
|
|
rt_init();
|
|
if_init();
|
|
config_init();
|
|
|
|
protos_build();
|
|
proto_build(&proto_unix_kernel);
|
|
proto_build(&proto_unix_iface);
|
|
}
|
|
|
|
void bt_bird_cleanup(void)
|
|
{
|
|
for (int i = 0; i < PROTOCOL__MAX; i++)
|
|
class_to_protocol[i] = NULL;
|
|
|
|
config = new_config = NULL;
|
|
the_bird_unlock();
|
|
}
|
|
|
|
static char *
|
|
bt_load_file(const char *filename, int quiet)
|
|
{
|
|
FILE *f = fopen(filename, "rb");
|
|
if (!quiet)
|
|
bt_assert_msg(f != NULL, "Open %s", filename);
|
|
|
|
if (f == NULL)
|
|
return NULL;
|
|
|
|
fseek(f, 0, SEEK_END);
|
|
long file_size_ = ftell(f);
|
|
fseek(f, 0, SEEK_SET);
|
|
|
|
if (file_size_ < 0)
|
|
return NULL;
|
|
|
|
size_t file_size = file_size_;
|
|
size_t read_size = 0;
|
|
|
|
char *file_body = mb_allocz(&root_pool, file_size+1);
|
|
|
|
/* XXX: copied from cf-lex.c */
|
|
errno=0;
|
|
while ((read_size += fread(file_body+read_size, 1, file_size-read_size, f)) != file_size && ferror(f))
|
|
{
|
|
bt_debug("iteration \n");
|
|
if(errno != EINTR)
|
|
{
|
|
bt_abort_msg("errno: %d", errno);
|
|
break;
|
|
}
|
|
errno=0;
|
|
clearerr(f);
|
|
}
|
|
fclose(f);
|
|
|
|
if (!quiet)
|
|
bt_assert_msg(read_size == file_size, "Read %s", filename);
|
|
|
|
return file_body;
|
|
}
|
|
|
|
static void
|
|
bt_show_cfg_error(const struct config *cfg)
|
|
{
|
|
int lino = 0;
|
|
int lino_delta = 5;
|
|
int lino_err = cfg->err_lino;
|
|
|
|
const char *str = bt_load_file(cfg->err_file_name, 1);
|
|
|
|
while (str && *str)
|
|
{
|
|
lino++;
|
|
if (BETWEEN(lino, lino_err - lino_delta, lino_err + lino_delta))
|
|
bt_debug("%4u%s", lino, (lino_err == lino ? " >> " : " "));
|
|
do
|
|
{
|
|
if (BETWEEN(lino, lino_err - lino_delta, lino_err + lino_delta))
|
|
bt_debug("%c", *str);
|
|
} while (*str && *(str++) != '\n');
|
|
}
|
|
bt_debug("\n");
|
|
}
|
|
|
|
static struct config *
|
|
bt_config_parse__(struct config *cfg)
|
|
{
|
|
bt_assert_msg(config_parse(cfg) == 1, "Parse %s", cfg->file_name);
|
|
|
|
if (cfg->err_msg)
|
|
{
|
|
bt_log("Parse error %s, line %d: %s", cfg->err_file_name, cfg->err_lino, cfg->err_msg);
|
|
bt_show_cfg_error(cfg);
|
|
return NULL;
|
|
}
|
|
|
|
config_commit(cfg, RECONFIG_HARD, 0);
|
|
new_config = cfg;
|
|
|
|
return cfg;
|
|
}
|
|
|
|
struct config *
|
|
bt_config_parse(const char *cfg_str)
|
|
{
|
|
struct config *cfg = config_alloc("configuration");
|
|
|
|
bt_config_parse_pos = cfg_str;
|
|
bt_config_parse_remain_len = strlen(cfg_str);
|
|
cf_read_hook = cf_static_read;
|
|
|
|
return bt_config_parse__(cfg);
|
|
}
|
|
|
|
struct config *
|
|
bt_config_file_parse(const char *filepath)
|
|
{
|
|
struct config *cfg = config_alloc(filepath);
|
|
|
|
cfg->file_fd = open(filepath, O_RDONLY);
|
|
bt_assert_msg(cfg->file_fd > 0, "Open %s", filepath);
|
|
if (cfg->file_fd < 0)
|
|
return NULL;
|
|
|
|
cf_read_hook = cf_file_read;
|
|
|
|
return bt_config_parse__(cfg);
|
|
}
|
|
|
|
/*
|
|
* Returns @base raised to the power of @power.
|
|
*/
|
|
uint
|
|
bt_naive_pow(uint base, uint power)
|
|
{
|
|
uint result = 1;
|
|
uint i;
|
|
for (i = 0; i < power; i++)
|
|
result *= base;
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* bytes_to_hex - transform data into hexadecimal representation
|
|
* @buf: preallocated string buffer
|
|
* @in_data: data for transformation
|
|
* @size: the length of @in_data
|
|
*
|
|
* This function transforms @in_data of length @size into hexadecimal
|
|
* representation and writes it into @buf.
|
|
*/
|
|
void
|
|
bt_bytes_to_hex(char *buf, const byte *in_data, size_t size)
|
|
{
|
|
size_t i;
|
|
for(i = 0; i < size; i++)
|
|
sprintf(buf + i*2, "%02x", in_data[i]);
|
|
}
|
|
|