]> git.ipfire.org Git - thirdparty/bird.git/blob - test/bt-utils.c
Doc: BFD update
[thirdparty/bird.git] / test / bt-utils.c
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