2 Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
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:
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
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
23 /* include zebra library */
36 #include "lib_errors.h"
38 #include "babel_main.h"
42 #include "babel_interface.h"
43 #include "neighbour.h"
48 #include "babel_zebra.h"
49 #include "babel_errors.h"
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);
58 struct thread_master
*master
; /* quagga's threads handler */
59 struct timeval babel_now
; /* current time */
61 unsigned char myid
[8]; /* unique id (mac address of an interface) */
64 int resend_delay
= -1;
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};
71 static const char *state_file
= DAEMON_VTY_DIR
"/babel-state";
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 */
77 static char babel_config_default
[] = SYSCONFDIR BABEL_DEFAULT_CONFIG
;
78 static char *babel_vty_addr
= NULL
;
79 static int babel_vty_port
= BABEL_VTY_PORT
;
81 /* babeld privileges */
82 static zebra_capabilities_t _caps_p
[] =
88 struct zebra_privs_t babeld_privs
=
97 .vty_group
= VTY_GROUP
,
100 .cap_num_p
= array_size(_caps_p
),
107 zlog_notice("Terminating on signal");
109 babel_exit_properly();
118 static struct quagga_signal_t babel_signals
[] =
122 .handler
= &babel_sigusr1
,
126 .handler
= &babel_sigexit
,
130 .handler
= &babel_sigexit
,
134 struct option longopts
[] =
139 FRR_DAEMON_INFO(babeld
, BABELD
,
140 .vty_port
= BABEL_VTY_PORT
,
141 .proghelp
= "Implementation of the BABEL routing protocol.",
143 .signals
= babel_signals
,
144 .n_signals
= array_size(babel_signals
),
146 .privs
= &babeld_privs
,
150 main(int argc
, char **argv
)
154 frr_preinit (&babeld_di
, argc
, argv
);
155 frr_opt_add ("", longopts
, "");
159 /* set the Babel's default link-local multicast address and Babel's port */
160 parse_address("ff02:0:0:0:0:0:1:6", protocol_group
, NULL
);
161 protocol_port
= 6696;
167 opt
= frr_getopt (argc
, argv
, NULL
);
182 /* create the threads handler */
183 master
= frr_init ();
188 resend_delay
= BABEL_DEFAULT_RESEND_DELAY
;
189 change_smoothing_half_life(BABEL_DEFAULT_SMOOTHING_HALF_LIFE
);
191 babel_replace_by_null(STDIN_FILENO
);
193 /* init some quagga's dependencies, and babeld's commands */
194 babeld_quagga_init();
195 /* init zebra client's structure and it's commands */
196 /* this replace kernel_setup && kernel_setup_socket */
197 babelz_zebra_init ();
200 rc
= resize_receive_buffer(1500);
204 schedule_neighbours_check(5000, 1);
218 /* initialize random value, and set 'babel_now' by the way. */
220 babel_init_random(void)
226 rc
= read_random_bytes(&seed
, sizeof(seed
));
228 flog_err_sys(EC_LIB_SYSTEM_CALL
, "read(random): %s",
229 safe_strerror(errno
));
233 seed
^= (babel_now
.tv_sec
^ babel_now
.tv_usec
);
238 close fd, and replace it by "/dev/null"
242 babel_replace_by_null(int fd
)
247 fd_null
= open("/dev/null", O_RDONLY
);
249 flog_err_sys(EC_LIB_SYSTEM_CALL
, "open(null): %s", safe_strerror(errno
));
253 rc
= dup2(fd_null
, fd
);
255 flog_err_sys(EC_LIB_SYSTEM_CALL
, "dup2(null, 0): %s",
256 safe_strerror(errno
));
264 Load the state file: check last babeld's running state, usefull in case of
265 "/etc/init.d/babeld restart"
268 babel_load_state_file(void)
273 fd
= open(state_file
, O_RDONLY
);
274 if(fd
< 0 && errno
!= ENOENT
)
275 flog_err_sys(EC_LIB_SYSTEM_CALL
, "open(babel-state: %s)",
276 safe_strerror(errno
));
277 rc
= unlink(state_file
);
278 if(fd
>= 0 && rc
< 0) {
279 flog_err_sys(EC_LIB_SYSTEM_CALL
, "unlink(babel-state): %s",
280 safe_strerror(errno
));
281 /* If we couldn't unlink it, it's probably stale. */
289 rc
= read(fd
, buf
, 99);
291 flog_err_sys(EC_LIB_SYSTEM_CALL
, "read(babel-state): %s",
292 safe_strerror(errno
));
295 rc
= sscanf(buf
, "%99s %d %ld\n", buf2
, &s
, &t
);
296 if(rc
== 3 && s
>= 0 && s
<= 0xFFFF) {
297 unsigned char sid
[8];
298 rc
= parse_eui64(buf2
, sid
);
300 flog_err(EC_BABEL_CONFIG
, "Couldn't parse babel-state.");
302 struct timeval realnow
;
303 debugf(BABEL_DEBUG_COMMON
,
304 "Got %s %d %ld from babel-state.",
305 format_eui64(sid
), s
, t
);
306 gettimeofday(&realnow
, NULL
);
307 if(memcmp(sid
, myid
, 8) == 0)
308 myseqno
= seqno_plus(s
, 1);
310 flog_err(EC_BABEL_CONFIG
,
311 "ID mismatch in babel-state. id=%s; old=%s",
316 flog_err(EC_BABEL_CONFIG
, "Couldn't parse babel-state.");
328 babel_exit_properly(void)
330 debugf(BABEL_DEBUG_COMMON
, "Exiting...");
331 usleep(roughly(10000));
334 /* Uninstall and flush all routes. */
335 debugf(BABEL_DEBUG_COMMON
, "Uninstall routes.");
337 babel_interface_close_all();
338 babel_zebra_close_connexion();
339 babel_save_state_file();
340 debugf(BABEL_DEBUG_COMMON
, "Remove pid file.");
341 debugf(BABEL_DEBUG_COMMON
, "Done.");
348 babel_save_state_file(void)
353 debugf(BABEL_DEBUG_COMMON
, "Save state file.");
354 fd
= open(state_file
, O_WRONLY
| O_TRUNC
| O_CREAT
, 0644);
356 flog_err_sys(EC_LIB_SYSTEM_CALL
, "creat(babel-state): %s",
357 safe_strerror(errno
));
360 struct timeval realnow
;
362 gettimeofday(&realnow
, NULL
);
363 rc
= snprintf(buf
, 100, "%s %d %ld\n",
364 format_eui64(myid
), (int)myseqno
,
365 (long)realnow
.tv_sec
);
366 if(rc
< 0 || rc
>= 100) {
367 flog_err(EC_BABEL_CONFIG
, "write(babel-state): overflow.");
370 rc
= write(fd
, buf
, rc
);
372 flog_err(EC_BABEL_CONFIG
, "write(babel-state): %s",
373 safe_strerror(errno
));
383 show_babel_main_configuration (struct vty
*vty
)
387 "configuration file = %s\n"
388 "protocol information:\n"
389 " multicast address = %s\n"
394 "kernel_metric = %d\n",
396 babeld_di
.config_file
? babeld_di
.config_file
: babel_config_default
,
397 format_address(protocol_group
),
399 babel_vty_addr
? babel_vty_addr
: "None",