]> git.proxmox.com Git - mirror_frr.git/blob - babeld/babel_main.c
Merge pull request #8353 from opensourcerouting/llvm-20210327
[mirror_frr.git] / babeld / babel_main.c
1 /*
2 Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE SOFTWARE.
21 */
22
23 /* include zebra library */
24 #include <zebra.h>
25 #include "getopt.h"
26 #include "if.h"
27 #include "log.h"
28 #include "thread.h"
29 #include "privs.h"
30 #include "sigevent.h"
31 #include "lib/version.h"
32 #include "command.h"
33 #include "vty.h"
34 #include "memory.h"
35 #include "libfrr.h"
36 #include "lib_errors.h"
37
38 #include "babel_main.h"
39 #include "babeld.h"
40 #include "util.h"
41 #include "kernel.h"
42 #include "babel_interface.h"
43 #include "neighbour.h"
44 #include "route.h"
45 #include "xroute.h"
46 #include "message.h"
47 #include "resend.h"
48 #include "babel_zebra.h"
49 #include "babel_errors.h"
50
51 static void babel_fail(void);
52 static void babel_init_random(void);
53 static void babel_replace_by_null(int fd);
54 static void babel_exit_properly(void);
55 static void babel_save_state_file(void);
56
57
58 struct thread_master *master; /* quagga's threads handler */
59 struct timeval babel_now; /* current time */
60
61 unsigned char myid[8]; /* unique id (mac address of an interface) */
62 int debug = 0;
63
64 int resend_delay = -1;
65
66 const unsigned char zeroes[16] = {0};
67 const unsigned char ones[16] =
68 {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
69 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
70
71 static char state_file[1024];
72
73 unsigned char protocol_group[16]; /* babel's link-local multicast address */
74 int protocol_port; /* babel's port */
75 int protocol_socket = -1; /* socket: communicate with others babeld */
76
77 static const char babel_config_default[] = SYSCONFDIR BABEL_DEFAULT_CONFIG;
78 static char *babel_vty_addr = NULL;
79 static int babel_vty_port = BABEL_VTY_PORT;
80
81 /* babeld privileges */
82 static zebra_capabilities_t _caps_p [] =
83 {
84 ZCAP_NET_RAW,
85 ZCAP_BIND
86 };
87
88 struct zebra_privs_t babeld_privs =
89 {
90 #if defined(FRR_USER)
91 .user = FRR_USER,
92 #endif
93 #if defined FRR_GROUP
94 .group = FRR_GROUP,
95 #endif
96 #ifdef VTY_GROUP
97 .vty_group = VTY_GROUP,
98 #endif
99 .caps_p = _caps_p,
100 .cap_num_p = array_size(_caps_p),
101 .cap_num_i = 0
102 };
103
104 static void
105 babel_sigexit(void)
106 {
107 zlog_notice("Terminating on signal");
108
109 babel_exit_properly();
110 }
111
112 static void
113 babel_sigusr1 (void)
114 {
115 zlog_rotate ();
116 }
117
118 static struct quagga_signal_t babel_signals[] =
119 {
120 {
121 .signal = SIGUSR1,
122 .handler = &babel_sigusr1,
123 },
124 {
125 .signal = SIGINT,
126 .handler = &babel_sigexit,
127 },
128 {
129 .signal = SIGTERM,
130 .handler = &babel_sigexit,
131 },
132 };
133
134 struct option longopts[] =
135 {
136 { 0 }
137 };
138
139 static const struct frr_yang_module_info *const babeld_yang_modules[] = {
140 &frr_filter_info,
141 &frr_interface_info,
142 &frr_vrf_info,
143 };
144
145 FRR_DAEMON_INFO(babeld, BABELD,
146 .vty_port = BABEL_VTY_PORT,
147 .proghelp = "Implementation of the BABEL routing protocol.",
148
149 .signals = babel_signals,
150 .n_signals = array_size(babel_signals),
151
152 .privs = &babeld_privs,
153
154 .yang_modules = babeld_yang_modules,
155 .n_yang_modules = array_size(babeld_yang_modules),
156 );
157
158 int
159 main(int argc, char **argv)
160 {
161 int rc;
162
163 frr_preinit (&babeld_di, argc, argv);
164 frr_opt_add ("", longopts, "");
165
166 babel_init_random();
167
168 /* set the Babel's default link-local multicast address and Babel's port */
169 parse_address("ff02:0:0:0:0:0:1:6", protocol_group, NULL);
170 protocol_port = 6696;
171
172 /* get options */
173 while(1) {
174 int opt;
175
176 opt = frr_getopt (argc, argv, NULL);
177
178 if (opt == EOF)
179 break;
180
181 switch (opt)
182 {
183 case 0:
184 break;
185 default:
186 frr_help_exit (1);
187 break;
188 }
189 }
190
191 snprintf(state_file, sizeof(state_file), "%s/%s",
192 frr_vtydir, "babel-state");
193
194 /* create the threads handler */
195 master = frr_init ();
196
197 /* Library inits. */
198 babel_error_init();
199
200 resend_delay = BABEL_DEFAULT_RESEND_DELAY;
201 change_smoothing_half_life(BABEL_DEFAULT_SMOOTHING_HALF_LIFE);
202
203 babel_replace_by_null(STDIN_FILENO);
204
205 /* init some quagga's dependencies, and babeld's commands */
206 if_zapi_callbacks(babel_ifp_create, babel_ifp_up,
207 babel_ifp_down, babel_ifp_destroy);
208 babeld_quagga_init();
209 /* init zebra client's structure and it's commands */
210 /* this replace kernel_setup && kernel_setup_socket */
211 babelz_zebra_init ();
212
213 /* init buffer */
214 rc = resize_receive_buffer(1500);
215 if(rc < 0)
216 babel_fail();
217
218 schedule_neighbours_check(5000, 1);
219
220 frr_config_fork();
221 frr_run(master);
222
223 return 0;
224 }
225
226 static void
227 babel_fail(void)
228 {
229 exit(1);
230 }
231
232 /* initialize random value, and set 'babel_now' by the way. */
233 static void
234 babel_init_random(void)
235 {
236 gettime(&babel_now);
237 int rc;
238 unsigned int seed;
239
240 rc = read_random_bytes(&seed, sizeof(seed));
241 if(rc < 0) {
242 flog_err_sys(EC_LIB_SYSTEM_CALL, "read(random): %s",
243 safe_strerror(errno));
244 seed = 42;
245 }
246
247 seed ^= (babel_now.tv_sec ^ babel_now.tv_usec);
248 srandom(seed);
249 }
250
251 /*
252 close fd, and replace it by "/dev/null"
253 exit if error
254 */
255 static void
256 babel_replace_by_null(int fd)
257 {
258 int fd_null;
259 int rc;
260
261 fd_null = open("/dev/null", O_RDONLY);
262 if(fd_null < 0) {
263 flog_err_sys(EC_LIB_SYSTEM_CALL, "open(null): %s", safe_strerror(errno));
264 exit(1);
265 }
266
267 rc = dup2(fd_null, fd);
268 if(rc < 0) {
269 flog_err_sys(EC_LIB_SYSTEM_CALL, "dup2(null, 0): %s",
270 safe_strerror(errno));
271 exit(1);
272 }
273
274 close(fd_null);
275 }
276
277 /*
278 Load the state file: check last babeld's running state, usefull in case of
279 "/etc/init.d/babeld restart"
280 */
281 void
282 babel_load_state_file(void)
283 {
284 int fd;
285 int rc;
286
287 fd = open(state_file, O_RDONLY);
288 if(fd < 0 && errno != ENOENT)
289 flog_err_sys(EC_LIB_SYSTEM_CALL, "open(babel-state: %s)",
290 safe_strerror(errno));
291 rc = unlink(state_file);
292 if(fd >= 0 && rc < 0) {
293 flog_err_sys(EC_LIB_SYSTEM_CALL, "unlink(babel-state): %s",
294 safe_strerror(errno));
295 /* If we couldn't unlink it, it's probably stale. */
296 goto fini;
297 }
298 if(fd >= 0) {
299 char buf[100];
300 char buf2[100];
301 int s;
302 long t;
303 rc = read(fd, buf, 99);
304 if(rc < 0) {
305 flog_err_sys(EC_LIB_SYSTEM_CALL, "read(babel-state): %s",
306 safe_strerror(errno));
307 } else {
308 buf[rc] = '\0';
309 rc = sscanf(buf, "%99s %d %ld\n", buf2, &s, &t);
310 if(rc == 3 && s >= 0 && s <= 0xFFFF) {
311 unsigned char sid[8];
312 rc = parse_eui64(buf2, sid);
313 if(rc < 0) {
314 flog_err(EC_BABEL_CONFIG, "Couldn't parse babel-state.");
315 } else {
316 struct timeval realnow;
317 debugf(BABEL_DEBUG_COMMON,
318 "Got %s %d %ld from babel-state.",
319 format_eui64(sid), s, t);
320 gettimeofday(&realnow, NULL);
321 if(memcmp(sid, myid, 8) == 0)
322 myseqno = seqno_plus(s, 1);
323 else
324 flog_err(EC_BABEL_CONFIG,
325 "ID mismatch in babel-state. id=%s; old=%s",
326 format_eui64(myid),
327 format_eui64(sid));
328 }
329 } else {
330 flog_err(EC_BABEL_CONFIG, "Couldn't parse babel-state.");
331 }
332 }
333 goto fini;
334 }
335 fini:
336 if (fd >= 0)
337 close(fd);
338 return ;
339 }
340
341 static void
342 babel_exit_properly(void)
343 {
344 debugf(BABEL_DEBUG_COMMON, "Exiting...");
345 usleep(roughly(10000));
346 gettime(&babel_now);
347
348 /* Uninstall and flush all routes. */
349 debugf(BABEL_DEBUG_COMMON, "Uninstall routes.");
350 flush_all_routes();
351 babel_interface_close_all();
352 babel_zebra_close_connexion();
353 babel_save_state_file();
354 debugf(BABEL_DEBUG_COMMON, "Remove pid file.");
355 debugf(BABEL_DEBUG_COMMON, "Done.");
356 frr_fini();
357
358 exit(0);
359 }
360
361 static void
362 babel_save_state_file(void)
363 {
364 int fd;
365 int rc;
366
367 debugf(BABEL_DEBUG_COMMON, "Save state file.");
368 fd = open(state_file, O_WRONLY | O_TRUNC | O_CREAT, 0644);
369 if(fd < 0) {
370 flog_err_sys(EC_LIB_SYSTEM_CALL, "creat(babel-state): %s",
371 safe_strerror(errno));
372 unlink(state_file);
373 } else {
374 struct timeval realnow;
375 char buf[100];
376 gettimeofday(&realnow, NULL);
377 rc = snprintf(buf, 100, "%s %d %ld\n",
378 format_eui64(myid), (int)myseqno,
379 (long)realnow.tv_sec);
380 if(rc < 0 || rc >= 100) {
381 flog_err(EC_BABEL_CONFIG, "write(babel-state): overflow.");
382 unlink(state_file);
383 } else {
384 rc = write(fd, buf, rc);
385 if(rc < 0) {
386 flog_err(EC_BABEL_CONFIG, "write(babel-state): %s",
387 safe_strerror(errno));
388 unlink(state_file);
389 }
390 fsync(fd);
391 }
392 close(fd);
393 }
394 }
395
396 void
397 show_babel_main_configuration (struct vty *vty)
398 {
399 vty_out (vty,
400 "state file = %s\n"
401 "configuration file = %s\n"
402 "protocol information:\n"
403 " multicast address = %s\n"
404 " port = %d\n"
405 "vty address = %s\n"
406 "vty port = %d\n"
407 "id = %s\n"
408 "kernel_metric = %d\n",
409 state_file,
410 babeld_di.config_file ? babeld_di.config_file : babel_config_default,
411 format_address(protocol_group),
412 protocol_port,
413 babel_vty_addr ? babel_vty_addr : "None",
414 babel_vty_port,
415 format_eui64(myid),
416 kernel_metric);
417 }