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