]> git.proxmox.com Git - mirror_frr.git/blame - babeld/babel_main.c
Merge pull request #12715 from opensourcerouting/fix/contribution_guid_squash_random_...
[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"
09781197 31#include "lib/version.h"
ca10883e
DS
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);
ca10883e
DS
53static void babel_exit_properly(void);
54static void babel_save_state_file(void);
55
56
57struct thread_master *master; /* quagga's threads handler */
58struct timeval babel_now; /* current time */
59
60unsigned char myid[8]; /* unique id (mac address of an interface) */
61int debug = 0;
62
63int resend_delay = -1;
64
65const unsigned char zeroes[16] = {0};
66const unsigned char ones[16] =
67 {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
68 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
69
43e587c1 70static char state_file[1024];
ca10883e
DS
71
72unsigned char protocol_group[16]; /* babel's link-local multicast address */
73int protocol_port; /* babel's port */
74int protocol_socket = -1; /* socket: communicate with others babeld */
75
2b64873d 76static const char babel_config_default[] = SYSCONFDIR BABEL_DEFAULT_CONFIG;
ca10883e
DS
77static char *babel_vty_addr = NULL;
78static int babel_vty_port = BABEL_VTY_PORT;
79
80/* babeld privileges */
81static zebra_capabilities_t _caps_p [] =
82{
83 ZCAP_NET_RAW,
84 ZCAP_BIND
85};
900b8c58 86
346526cc 87struct zebra_privs_t babeld_privs =
ca10883e 88{
dd329373
DS
89#if defined(FRR_USER)
90 .user = FRR_USER,
ca10883e 91#endif
dd329373
DS
92#if defined FRR_GROUP
93 .group = FRR_GROUP,
ca10883e
DS
94#endif
95#ifdef VTY_GROUP
96 .vty_group = VTY_GROUP,
97#endif
98 .caps_p = _caps_p,
900b8c58 99 .cap_num_p = array_size(_caps_p),
ca10883e
DS
100 .cap_num_i = 0
101};
102
103static void
104babel_sigexit(void)
105{
106 zlog_notice("Terminating on signal");
107
108 babel_exit_properly();
109}
110
111static void
112babel_sigusr1 (void)
113{
114 zlog_rotate ();
115}
116
7cc91e67 117static struct frr_signal_t babel_signals[] =
ca10883e
DS
118 {
119 {
120 .signal = SIGUSR1,
121 .handler = &babel_sigusr1,
122 },
123 {
124 .signal = SIGINT,
125 .handler = &babel_sigexit,
126 },
127 {
128 .signal = SIGTERM,
129 .handler = &babel_sigexit,
130 },
131 };
132
133struct option longopts[] =
134 {
135 { 0 }
136 };
137
6fd8972a 138static const struct frr_yang_module_info *const babeld_yang_modules[] = {
fb7f5aa8 139 &frr_filter_info,
6fd8972a
CS
140 &frr_interface_info,
141 &frr_vrf_info,
142};
8fcdd0d6 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),
80413c20 155);
ca10883e
DS
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:
d10bda27 185 frr_help_exit(1);
ca10883e
DS
186 }
187 }
188
3c649c71
DS
189 snprintf(state_file, sizeof(state_file), "%s/%s",
190 frr_vtydir, "babel-state");
191
ca10883e 192 /* create the threads handler */
900b8c58 193 master = frr_init ();
ca10883e
DS
194
195 /* Library inits. */
f135ba52 196 babel_error_init();
ca10883e
DS
197
198 resend_delay = BABEL_DEFAULT_RESEND_DELAY;
199 change_smoothing_half_life(BABEL_DEFAULT_SMOOTHING_HALF_LIFE);
200
ca10883e 201 /* init some quagga's dependencies, and babeld's commands */
138c5a74
DS
202 if_zapi_callbacks(babel_ifp_create, babel_ifp_up,
203 babel_ifp_down, babel_ifp_destroy);
ca10883e
DS
204 babeld_quagga_init();
205 /* init zebra client's structure and it's commands */
206 /* this replace kernel_setup && kernel_setup_socket */
207 babelz_zebra_init ();
208
ca10883e
DS
209 /* init buffer */
210 rc = resize_receive_buffer(1500);
211 if(rc < 0)
212 babel_fail();
213
214 schedule_neighbours_check(5000, 1);
215
900b8c58
DS
216 frr_config_fork();
217 frr_run(master);
218
219 return 0;
ca10883e
DS
220}
221
222static void
223babel_fail(void)
224{
225 exit(1);
226}
227
228/* initialize random value, and set 'babel_now' by the way. */
229static void
230babel_init_random(void)
231{
232 gettime(&babel_now);
233 int rc;
234 unsigned int seed;
235
236 rc = read_random_bytes(&seed, sizeof(seed));
237 if(rc < 0) {
450971aa 238 flog_err_sys(EC_LIB_SYSTEM_CALL, "read(random): %s",
f135ba52 239 safe_strerror(errno));
ca10883e
DS
240 seed = 42;
241 }
242
243 seed ^= (babel_now.tv_sec ^ babel_now.tv_usec);
244 srandom(seed);
245}
246
ca10883e
DS
247/*
248 Load the state file: check last babeld's running state, usefull in case of
249 "/etc/init.d/babeld restart"
250 */
251void
252babel_load_state_file(void)
253{
254 int fd;
255 int rc;
256
257 fd = open(state_file, O_RDONLY);
258 if(fd < 0 && errno != ENOENT)
450971aa 259 flog_err_sys(EC_LIB_SYSTEM_CALL, "open(babel-state: %s)",
f135ba52 260 safe_strerror(errno));
ca10883e
DS
261 rc = unlink(state_file);
262 if(fd >= 0 && rc < 0) {
450971aa 263 flog_err_sys(EC_LIB_SYSTEM_CALL, "unlink(babel-state): %s",
f135ba52 264 safe_strerror(errno));
ca10883e 265 /* If we couldn't unlink it, it's probably stale. */
c31a793b 266 goto fini;
ca10883e
DS
267 }
268 if(fd >= 0) {
269 char buf[100];
270 char buf2[100];
271 int s;
272 long t;
273 rc = read(fd, buf, 99);
274 if(rc < 0) {
450971aa 275 flog_err_sys(EC_LIB_SYSTEM_CALL, "read(babel-state): %s",
f135ba52 276 safe_strerror(errno));
ca10883e
DS
277 } else {
278 buf[rc] = '\0';
279 rc = sscanf(buf, "%99s %d %ld\n", buf2, &s, &t);
280 if(rc == 3 && s >= 0 && s <= 0xFFFF) {
281 unsigned char sid[8];
282 rc = parse_eui64(buf2, sid);
283 if(rc < 0) {
5b003f31 284 flog_err(EC_BABEL_CONFIG, "Couldn't parse babel-state.");
ca10883e
DS
285 } else {
286 struct timeval realnow;
287 debugf(BABEL_DEBUG_COMMON,
288 "Got %s %d %ld from babel-state.",
289 format_eui64(sid), s, t);
290 gettimeofday(&realnow, NULL);
291 if(memcmp(sid, myid, 8) == 0)
292 myseqno = seqno_plus(s, 1);
293 else
5b003f31 294 flog_err(EC_BABEL_CONFIG,
e33b116c 295 "ID mismatch in babel-state. id=%s; old=%s",
ca10883e
DS
296 format_eui64(myid),
297 format_eui64(sid));
298 }
299 } else {
5b003f31 300 flog_err(EC_BABEL_CONFIG, "Couldn't parse babel-state.");
ca10883e
DS
301 }
302 }
c31a793b 303 goto fini;
ca10883e 304 }
c31a793b
VJ
305fini:
306 if (fd >= 0)
307 close(fd);
308 return ;
ca10883e
DS
309}
310
311static void
312babel_exit_properly(void)
313{
314 debugf(BABEL_DEBUG_COMMON, "Exiting...");
315 usleep(roughly(10000));
316 gettime(&babel_now);
317
318 /* Uninstall and flush all routes. */
319 debugf(BABEL_DEBUG_COMMON, "Uninstall routes.");
320 flush_all_routes();
321 babel_interface_close_all();
322 babel_zebra_close_connexion();
323 babel_save_state_file();
324 debugf(BABEL_DEBUG_COMMON, "Remove pid file.");
325 debugf(BABEL_DEBUG_COMMON, "Done.");
8879bd22 326 frr_fini();
ca10883e
DS
327
328 exit(0);
329}
330
331static void
332babel_save_state_file(void)
333{
334 int fd;
335 int rc;
336
337 debugf(BABEL_DEBUG_COMMON, "Save state file.");
338 fd = open(state_file, O_WRONLY | O_TRUNC | O_CREAT, 0644);
339 if(fd < 0) {
450971aa 340 flog_err_sys(EC_LIB_SYSTEM_CALL, "creat(babel-state): %s",
f135ba52 341 safe_strerror(errno));
ca10883e
DS
342 unlink(state_file);
343 } else {
344 struct timeval realnow;
345 char buf[100];
346 gettimeofday(&realnow, NULL);
347 rc = snprintf(buf, 100, "%s %d %ld\n",
348 format_eui64(myid), (int)myseqno,
349 (long)realnow.tv_sec);
350 if(rc < 0 || rc >= 100) {
5b003f31 351 flog_err(EC_BABEL_CONFIG, "write(babel-state): overflow.");
ca10883e
DS
352 unlink(state_file);
353 } else {
354 rc = write(fd, buf, rc);
355 if(rc < 0) {
5b003f31 356 flog_err(EC_BABEL_CONFIG, "write(babel-state): %s",
e33b116c 357 safe_strerror(errno));
ca10883e
DS
358 unlink(state_file);
359 }
360 fsync(fd);
361 }
362 close(fd);
363 }
364}
365
366void
367show_babel_main_configuration (struct vty *vty)
368{
181039f3 369 vty_out (vty,
cdda2010
DL
370 "state file = %s\n"
371 "configuration file = %s\n"
0437e105 372 "protocol information:\n"
cdda2010
DL
373 " multicast address = %s\n"
374 " port = %d\n"
375 "vty address = %s\n"
376 "vty port = %d\n"
377 "id = %s\n"
181039f3 378 "kernel_metric = %d\n",
cdda2010 379 state_file,
f714218e 380 babeld_di.config_file ? babeld_di.config_file : babel_config_default,
cdda2010
DL
381 format_address(protocol_group),
382 protocol_port,
ca10883e 383 babel_vty_addr ? babel_vty_addr : "None",
cdda2010
DL
384 babel_vty_port,
385 format_eui64(myid),
96ade3ed 386 kernel_metric);
ca10883e 387}