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 */
37 #include "babel_main.h"
41 #include "babel_interface.h"
42 #include "neighbour.h"
47 #include "babel_zebra.h"
49 static void babel_fail(void);
50 static void babel_init_random(void);
51 static void babel_replace_by_null(int fd
);
52 static void babel_exit_properly(void);
53 static void babel_save_state_file(void);
56 struct thread_master
*master
; /* quagga's threads handler */
57 struct timeval babel_now
; /* current time */
59 unsigned char myid
[8]; /* unique id (mac address of an interface) */
62 int resend_delay
= -1;
64 const unsigned char zeroes
[16] = {0};
65 const unsigned char ones
[16] =
66 {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
67 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
69 static const char *state_file
= DAEMON_VTY_DIR
"/babel-state";
71 unsigned char protocol_group
[16]; /* babel's link-local multicast address */
72 int protocol_port
; /* babel's port */
73 int protocol_socket
= -1; /* socket: communicate with others babeld */
75 static char babel_config_default
[] = SYSCONFDIR BABEL_DEFAULT_CONFIG
;
76 static char *babel_vty_addr
= NULL
;
77 static int babel_vty_port
= BABEL_VTY_PORT
;
79 /* babeld privileges */
80 static zebra_capabilities_t _caps_p
[] =
86 struct zebra_privs_t babeld_privs
=
95 .vty_group
= VTY_GROUP
,
98 .cap_num_p
= array_size(_caps_p
),
105 zlog_notice("Terminating on signal");
107 babel_exit_properly();
116 static struct quagga_signal_t babel_signals
[] =
120 .handler
= &babel_sigusr1
,
124 .handler
= &babel_sigexit
,
128 .handler
= &babel_sigexit
,
132 struct option longopts
[] =
137 FRR_DAEMON_INFO(babeld
, BABELD
,
138 .vty_port
= BABEL_VTY_PORT
,
139 .proghelp
= "Implementation of the BABEL routing protocol.",
141 .signals
= babel_signals
,
142 .n_signals
= array_size(babel_signals
),
144 .privs
= &babeld_privs
,
148 main(int argc
, char **argv
)
152 frr_preinit (&babeld_di
, argc
, argv
);
153 frr_opt_add ("", longopts
, "");
157 /* set the Babel's default link-local multicast address and Babel's port */
158 parse_address("ff02:0:0:0:0:0:1:6", protocol_group
, NULL
);
159 protocol_port
= 6696;
165 opt
= frr_getopt (argc
, argv
, NULL
);
180 /* create the threads handler */
181 master
= frr_init ();
184 zprivs_init (&babeld_privs
);
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 ();
199 /* Get zebra configuration file. */
200 vty_read_config (babeld_di
.config_file
, babel_config_default
);
203 rc
= resize_receive_buffer(1500);
207 schedule_neighbours_check(5000, 1);
221 /* initialize random value, and set 'babel_now' by the way. */
223 babel_init_random(void)
229 rc
= read_random_bytes(&seed
, sizeof(seed
));
231 zlog_err("read(random): %s", safe_strerror(errno
));
235 seed
^= (babel_now
.tv_sec
^ babel_now
.tv_usec
);
240 close fd, and replace it by "/dev/null"
244 babel_replace_by_null(int fd
)
249 fd_null
= open("/dev/null", O_RDONLY
);
251 zlog_err("open(null): %s", safe_strerror(errno
));
255 rc
= dup2(fd_null
, fd
);
257 zlog_err("dup2(null, 0): %s", safe_strerror(errno
));
265 Load the state file: check last babeld's running state, usefull in case of
266 "/etc/init.d/babeld restart"
269 babel_load_state_file(void)
274 fd
= open(state_file
, O_RDONLY
);
275 if(fd
< 0 && errno
!= ENOENT
)
276 zlog_err("open(babel-state: %s)", safe_strerror(errno
));
277 rc
= unlink(state_file
);
278 if(fd
>= 0 && rc
< 0) {
279 zlog_err("unlink(babel-state): %s", safe_strerror(errno
));
280 /* If we couldn't unlink it, it's probably stale. */
288 rc
= read(fd
, buf
, 99);
290 zlog_err("read(babel-state): %s", safe_strerror(errno
));
293 rc
= sscanf(buf
, "%99s %d %ld\n", buf2
, &s
, &t
);
294 if(rc
== 3 && s
>= 0 && s
<= 0xFFFF) {
295 unsigned char sid
[8];
296 rc
= parse_eui64(buf2
, sid
);
298 zlog_err("Couldn't parse babel-state.");
300 struct timeval realnow
;
301 debugf(BABEL_DEBUG_COMMON
,
302 "Got %s %d %ld from babel-state.",
303 format_eui64(sid
), s
, t
);
304 gettimeofday(&realnow
, NULL
);
305 if(memcmp(sid
, myid
, 8) == 0)
306 myseqno
= seqno_plus(s
, 1);
308 zlog_err("ID mismatch in babel-state. id=%s; old=%s",
313 zlog_err("Couldn't parse babel-state.");
325 babel_exit_properly(void)
327 debugf(BABEL_DEBUG_COMMON
, "Exiting...");
328 usleep(roughly(10000));
331 /* Uninstall and flush all routes. */
332 debugf(BABEL_DEBUG_COMMON
, "Uninstall routes.");
334 babel_interface_close_all();
335 babel_zebra_close_connexion();
336 babel_save_state_file();
337 debugf(BABEL_DEBUG_COMMON
, "Remove pid file.");
338 debugf(BABEL_DEBUG_COMMON
, "Done.");
345 babel_save_state_file(void)
350 debugf(BABEL_DEBUG_COMMON
, "Save state file.");
351 fd
= open(state_file
, O_WRONLY
| O_TRUNC
| O_CREAT
, 0644);
353 zlog_err("creat(babel-state): %s", safe_strerror(errno
));
356 struct timeval realnow
;
358 gettimeofday(&realnow
, NULL
);
359 rc
= snprintf(buf
, 100, "%s %d %ld\n",
360 format_eui64(myid
), (int)myseqno
,
361 (long)realnow
.tv_sec
);
362 if(rc
< 0 || rc
>= 100) {
363 zlog_err("write(babel-state): overflow.");
366 rc
= write(fd
, buf
, rc
);
368 zlog_err("write(babel-state): %s", safe_strerror(errno
));
378 show_babel_main_configuration (struct vty
*vty
)
382 "configuration file = %s\n"
383 "protocol informations:\n"
384 " multicast address = %s\n"
389 "kernel_metric = %d\n",
391 babeld_di
.config_file
? babeld_di
.config_file
: babel_config_default
,
392 format_address(protocol_group
),
394 babel_vty_addr
? babel_vty_addr
: "None",