1: /*
2: * BIRD Test -- Utils for testing parsing configuration file
3: *
4: * (c) 2015 CZ.NIC z.s.p.o.
5: *
6: * Can be freely distributed and used under the terms of the GNU GPL.
7: */
8:
9: #include <stdlib.h>
10: #include <fcntl.h>
11: #include <unistd.h>
12:
13: #include "test/birdtest.h"
14: #include "test/bt-utils.h"
15:
16: #include "nest/bird.h"
17: #include "nest/route.h"
18: #include "nest/protocol.h"
19:
20: #include "sysdep/unix/unix.h"
21: #include "sysdep/unix/krt.h"
22:
23: #include "nest/iface.h"
24: #include "nest/locks.h"
25:
26: #include "filter/filter.h"
27:
28: #define BETWEEN(a, b, c) (((a) >= (b)) && ((a) <= (c)))
29:
30: static const byte *bt_config_parse_pos;
31: static uint bt_config_parse_remain_len;
32:
33: /* This is cf_read_hook for hard-coded text configuration */
34: static int
35: cf_static_read(byte *dest, uint max_len, int fd UNUSED)
36: {
37: if (max_len > bt_config_parse_remain_len)
38: max_len = bt_config_parse_remain_len;
39: memcpy(dest, bt_config_parse_pos, max_len);
40: bt_config_parse_pos += max_len;
41: bt_config_parse_remain_len -= max_len;
42: return max_len;
43: }
44:
45: /* This is cf_read_hook for reading configuration files,
46: * function is copied from main.c, cf_read() */
47: static int
48: cf_file_read(byte *dest, uint max_len, int fd)
49: {
50: int l = read(fd, dest, max_len);
51: if (l < 0)
52: cf_error("Read error");
53: return l;
54: }
55:
56: void
57: bt_bird_init(void)
58: {
59: if(bt_verbose)
60: log_init_debug("");
61: log_switch(bt_verbose != 0, NULL, NULL);
62:
63: resource_init();
64: olock_init();
65: timer_init();
66: io_init();
67: rt_init();
68: if_init();
69: config_init();
70:
71: protos_build();
72: proto_build(&proto_unix_kernel);
73: proto_build(&proto_unix_iface);
74: }
75:
76: void bt_bird_cleanup(void)
77: {
78: for (int i = 0; i < PROTOCOL__MAX; i++)
79: class_to_protocol[i] = NULL;
80:
81: config = new_config = NULL;
82: }
83:
84: static char *
85: bt_load_file(const char *filename, int quiet)
86: {
87: FILE *f = fopen(filename, "rb");
88: if (!quiet)
89: bt_assert_msg(f != NULL, "Open %s", filename);
90:
91: if (f == NULL)
92: return NULL;
93:
94: fseek(f, 0, SEEK_END);
95: long file_size_ = ftell(f);
96: fseek(f, 0, SEEK_SET);
97:
98: if (file_size_ < 0)
99: return NULL;
100:
101: size_t file_size = file_size_;
102: size_t read_size = 0;
103:
104: char *file_body = mb_allocz(&root_pool, file_size+1);
105:
106: /* XXX: copied from cf-lex.c */
107: errno=0;
108: while ((read_size += fread(file_body+read_size, 1, file_size-read_size, f)) != file_size && ferror(f))
109: {
110: bt_debug("iteration \n");
111: if(errno != EINTR)
112: {
113: bt_abort_msg("errno: %d", errno);
114: break;
115: }
116: errno=0;
117: clearerr(f);
118: }
119: fclose(f);
120:
121: if (!quiet)
122: bt_assert_msg(read_size == file_size, "Read %s", filename);
123:
124: return file_body;
125: }
126:
127: static void
128: bt_show_cfg_error(const struct config *cfg)
129: {
130: int lino = 0;
131: int lino_delta = 5;
132: int lino_err = cfg->err_lino;
133:
134: const char *str = bt_load_file(cfg->err_file_name, 1);
135:
136: while (str && *str)
137: {
138: lino++;
139: if (BETWEEN(lino, lino_err - lino_delta, lino_err + lino_delta))
140: bt_debug("%4u%s", lino, (lino_err == lino ? " >> " : " "));
141: do
142: {
143: if (BETWEEN(lino, lino_err - lino_delta, lino_err + lino_delta))
144: bt_debug("%c", *str);
145: } while (*str && *(str++) != '\n');
146: }
147: bt_debug("\n");
148: }
149:
150: static struct config *
151: bt_config_parse__(struct config *cfg)
152: {
153: bt_assert_msg(config_parse(cfg) == 1, "Parse %s", cfg->file_name);
154:
155: if (cfg->err_msg)
156: {
157: bt_debug("Parse error %s, line %d: %s\n", cfg->err_file_name, cfg->err_lino, cfg->err_msg);
158: bt_show_cfg_error(cfg);
159: return NULL;
160: }
161:
162: config_commit(cfg, RECONFIG_HARD, 0);
163: new_config = cfg;
164:
165: return cfg;
166: }
167:
168: struct config *
169: bt_config_parse(const char *cfg_str)
170: {
171: struct config *cfg = config_alloc("configuration");
172:
173: bt_config_parse_pos = cfg_str;
174: bt_config_parse_remain_len = strlen(cfg_str);
175: cf_read_hook = cf_static_read;
176:
177: return bt_config_parse__(cfg);
178: }
179:
180: struct config *
181: bt_config_file_parse(const char *filepath)
182: {
183: struct config *cfg = config_alloc(filepath);
184:
185: cfg->file_fd = open(filepath, O_RDONLY);
186: bt_assert_msg(cfg->file_fd > 0, "Open %s", filepath);
187: if (cfg->file_fd < 0)
188: return NULL;
189:
190: cf_read_hook = cf_file_read;
191:
192: return bt_config_parse__(cfg);
193: }
194:
195: /*
196: * Returns @base raised to the power of @power.
197: */
198: uint
199: bt_naive_pow(uint base, uint power)
200: {
201: uint result = 1;
202: uint i;
203: for (i = 0; i < power; i++)
204: result *= base;
205: return result;
206: }
207:
208: /**
209: * bytes_to_hex - transform data into hexadecimal representation
210: * @buf: preallocated string buffer
211: * @in_data: data for transformation
212: * @size: the length of @in_data
213: *
214: * This function transforms @in_data of length @size into hexadecimal
215: * representation and writes it into @buf.
216: */
217: void
218: bt_bytes_to_hex(char *buf, const byte *in_data, size_t size)
219: {
220: size_t i;
221: for(i = 0; i < size; i++)
222: sprintf(buf + i*2, "%02x", in_data[i]);
223: }
224:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>