]> git.proxmox.com Git - mirror_frr.git/blame - babeld/babel_main.c
Merge pull request #3051 from mitch-skiba/addpath_change_V1
[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
71static const char *state_file = DAEMON_VTY_DIR "/babel-state";
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
77static 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
8fcdd0d6
RW
139static const struct frr_yang_module_info *babeld_yang_modules[] =
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
190 /* create the threads handler */
900b8c58 191 master = frr_init ();
ca10883e
DS
192
193 /* Library inits. */
f135ba52 194 babel_error_init();
ca10883e
DS
195
196 resend_delay = BABEL_DEFAULT_RESEND_DELAY;
197 change_smoothing_half_life(BABEL_DEFAULT_SMOOTHING_HALF_LIFE);
198
199 babel_replace_by_null(STDIN_FILENO);
200
201 /* init some quagga's dependencies, and babeld's commands */
202 babeld_quagga_init();
203 /* init zebra client's structure and it's commands */
204 /* this replace kernel_setup && kernel_setup_socket */
205 babelz_zebra_init ();
206
ca10883e
DS
207 /* init buffer */
208 rc = resize_receive_buffer(1500);
209 if(rc < 0)
210 babel_fail();
211
212 schedule_neighbours_check(5000, 1);
213
900b8c58
DS
214 frr_config_fork();
215 frr_run(master);
216
217 return 0;
ca10883e
DS
218}
219
220static void
221babel_fail(void)
222{
223 exit(1);
224}
225
226/* initialize random value, and set 'babel_now' by the way. */
227static void
228babel_init_random(void)
229{
230 gettime(&babel_now);
231 int rc;
232 unsigned int seed;
233
234 rc = read_random_bytes(&seed, sizeof(seed));
235 if(rc < 0) {
450971aa 236 flog_err_sys(EC_LIB_SYSTEM_CALL, "read(random): %s",
f135ba52 237 safe_strerror(errno));
ca10883e
DS
238 seed = 42;
239 }
240
241 seed ^= (babel_now.tv_sec ^ babel_now.tv_usec);
242 srandom(seed);
243}
244
245/*
246 close fd, and replace it by "/dev/null"
247 exit if error
248 */
249static void
250babel_replace_by_null(int fd)
251{
252 int fd_null;
253 int rc;
254
255 fd_null = open("/dev/null", O_RDONLY);
256 if(fd_null < 0) {
450971aa 257 flog_err_sys(EC_LIB_SYSTEM_CALL, "open(null): %s", safe_strerror(errno));
ca10883e
DS
258 exit(1);
259 }
260
261 rc = dup2(fd_null, fd);
262 if(rc < 0) {
450971aa 263 flog_err_sys(EC_LIB_SYSTEM_CALL, "dup2(null, 0): %s",
f135ba52 264 safe_strerror(errno));
ca10883e
DS
265 exit(1);
266 }
267
268 close(fd_null);
269}
270
271/*
272 Load the state file: check last babeld's running state, usefull in case of
273 "/etc/init.d/babeld restart"
274 */
275void
276babel_load_state_file(void)
277{
278 int fd;
279 int rc;
280
281 fd = open(state_file, O_RDONLY);
282 if(fd < 0 && errno != ENOENT)
450971aa 283 flog_err_sys(EC_LIB_SYSTEM_CALL, "open(babel-state: %s)",
f135ba52 284 safe_strerror(errno));
ca10883e
DS
285 rc = unlink(state_file);
286 if(fd >= 0 && rc < 0) {
450971aa 287 flog_err_sys(EC_LIB_SYSTEM_CALL, "unlink(babel-state): %s",
f135ba52 288 safe_strerror(errno));
ca10883e 289 /* If we couldn't unlink it, it's probably stale. */
c31a793b 290 goto fini;
ca10883e
DS
291 }
292 if(fd >= 0) {
293 char buf[100];
294 char buf2[100];
295 int s;
296 long t;
297 rc = read(fd, buf, 99);
298 if(rc < 0) {
450971aa 299 flog_err_sys(EC_LIB_SYSTEM_CALL, "read(babel-state): %s",
f135ba52 300 safe_strerror(errno));
ca10883e
DS
301 } else {
302 buf[rc] = '\0';
303 rc = sscanf(buf, "%99s %d %ld\n", buf2, &s, &t);
304 if(rc == 3 && s >= 0 && s <= 0xFFFF) {
305 unsigned char sid[8];
306 rc = parse_eui64(buf2, sid);
307 if(rc < 0) {
5b003f31 308 flog_err(EC_BABEL_CONFIG, "Couldn't parse babel-state.");
ca10883e
DS
309 } else {
310 struct timeval realnow;
311 debugf(BABEL_DEBUG_COMMON,
312 "Got %s %d %ld from babel-state.",
313 format_eui64(sid), s, t);
314 gettimeofday(&realnow, NULL);
315 if(memcmp(sid, myid, 8) == 0)
316 myseqno = seqno_plus(s, 1);
317 else
5b003f31 318 flog_err(EC_BABEL_CONFIG,
e33b116c 319 "ID mismatch in babel-state. id=%s; old=%s",
ca10883e
DS
320 format_eui64(myid),
321 format_eui64(sid));
322 }
323 } else {
5b003f31 324 flog_err(EC_BABEL_CONFIG, "Couldn't parse babel-state.");
ca10883e
DS
325 }
326 }
c31a793b 327 goto fini;
ca10883e 328 }
c31a793b
VJ
329fini:
330 if (fd >= 0)
331 close(fd);
332 return ;
ca10883e
DS
333}
334
335static void
336babel_exit_properly(void)
337{
338 debugf(BABEL_DEBUG_COMMON, "Exiting...");
339 usleep(roughly(10000));
340 gettime(&babel_now);
341
342 /* Uninstall and flush all routes. */
343 debugf(BABEL_DEBUG_COMMON, "Uninstall routes.");
344 flush_all_routes();
345 babel_interface_close_all();
346 babel_zebra_close_connexion();
347 babel_save_state_file();
348 debugf(BABEL_DEBUG_COMMON, "Remove pid file.");
349 debugf(BABEL_DEBUG_COMMON, "Done.");
8879bd22 350 frr_fini();
ca10883e
DS
351
352 exit(0);
353}
354
355static void
356babel_save_state_file(void)
357{
358 int fd;
359 int rc;
360
361 debugf(BABEL_DEBUG_COMMON, "Save state file.");
362 fd = open(state_file, O_WRONLY | O_TRUNC | O_CREAT, 0644);
363 if(fd < 0) {
450971aa 364 flog_err_sys(EC_LIB_SYSTEM_CALL, "creat(babel-state): %s",
f135ba52 365 safe_strerror(errno));
ca10883e
DS
366 unlink(state_file);
367 } else {
368 struct timeval realnow;
369 char buf[100];
370 gettimeofday(&realnow, NULL);
371 rc = snprintf(buf, 100, "%s %d %ld\n",
372 format_eui64(myid), (int)myseqno,
373 (long)realnow.tv_sec);
374 if(rc < 0 || rc >= 100) {
5b003f31 375 flog_err(EC_BABEL_CONFIG, "write(babel-state): overflow.");
ca10883e
DS
376 unlink(state_file);
377 } else {
378 rc = write(fd, buf, rc);
379 if(rc < 0) {
5b003f31 380 flog_err(EC_BABEL_CONFIG, "write(babel-state): %s",
e33b116c 381 safe_strerror(errno));
ca10883e
DS
382 unlink(state_file);
383 }
384 fsync(fd);
385 }
386 close(fd);
387 }
388}
389
390void
391show_babel_main_configuration (struct vty *vty)
392{
181039f3 393 vty_out (vty,
cdda2010
DL
394 "state file = %s\n"
395 "configuration file = %s\n"
0437e105 396 "protocol information:\n"
cdda2010
DL
397 " multicast address = %s\n"
398 " port = %d\n"
399 "vty address = %s\n"
400 "vty port = %d\n"
401 "id = %s\n"
181039f3 402 "kernel_metric = %d\n",
cdda2010 403 state_file,
f714218e 404 babeld_di.config_file ? babeld_di.config_file : babel_config_default,
cdda2010
DL
405 format_address(protocol_group),
406 protocol_port,
ca10883e 407 babel_vty_addr ? babel_vty_addr : "None",
cdda2010
DL
408 babel_vty_port,
409 format_eui64(myid),
96ade3ed 410 kernel_metric);
ca10883e 411}