]> git.proxmox.com Git - mirror_frr.git/blame - babeld/babel_main.c
build: fix protobuf out-of-tree build
[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
6fd8972a 139static const struct frr_yang_module_info *const babeld_yang_modules[] = {
fb7f5aa8 140 &frr_filter_info,
6fd8972a
CS
141 &frr_interface_info,
142 &frr_vrf_info,
143};
8fcdd0d6 144
ca10883e
DS
145FRR_DAEMON_INFO(babeld, BABELD,
146 .vty_port = BABEL_VTY_PORT,
147 .proghelp = "Implementation of the BABEL routing protocol.",
148
149 .signals = babel_signals,
150 .n_signals = array_size(babel_signals),
151
152 .privs = &babeld_privs,
8fcdd0d6
RW
153
154 .yang_modules = babeld_yang_modules,
155 .n_yang_modules = array_size(babeld_yang_modules),
80413c20 156);
ca10883e
DS
157
158int
159main(int argc, char **argv)
160{
900b8c58 161 int rc;
ca10883e 162
900b8c58
DS
163 frr_preinit (&babeld_di, argc, argv);
164 frr_opt_add ("", longopts, "");
f135ba52 165
ca10883e
DS
166 babel_init_random();
167
168 /* set the Babel's default link-local multicast address and Babel's port */
169 parse_address("ff02:0:0:0:0:0:1:6", protocol_group, NULL);
170 protocol_port = 6696;
171
172 /* get options */
173 while(1) {
174 int opt;
175
176 opt = frr_getopt (argc, argv, NULL);
177
178 if (opt == EOF)
179 break;
180
181 switch (opt)
182 {
183 case 0:
184 break;
185 default:
186 frr_help_exit (1);
187 break;
188 }
189 }
190
3c649c71
DS
191 snprintf(state_file, sizeof(state_file), "%s/%s",
192 frr_vtydir, "babel-state");
193
ca10883e 194 /* create the threads handler */
900b8c58 195 master = frr_init ();
ca10883e
DS
196
197 /* Library inits. */
f135ba52 198 babel_error_init();
ca10883e
DS
199
200 resend_delay = BABEL_DEFAULT_RESEND_DELAY;
201 change_smoothing_half_life(BABEL_DEFAULT_SMOOTHING_HALF_LIFE);
202
203 babel_replace_by_null(STDIN_FILENO);
204
205 /* init some quagga's dependencies, and babeld's commands */
138c5a74
DS
206 if_zapi_callbacks(babel_ifp_create, babel_ifp_up,
207 babel_ifp_down, babel_ifp_destroy);
ca10883e
DS
208 babeld_quagga_init();
209 /* init zebra client's structure and it's commands */
210 /* this replace kernel_setup && kernel_setup_socket */
211 babelz_zebra_init ();
212
ca10883e
DS
213 /* init buffer */
214 rc = resize_receive_buffer(1500);
215 if(rc < 0)
216 babel_fail();
217
218 schedule_neighbours_check(5000, 1);
219
900b8c58
DS
220 frr_config_fork();
221 frr_run(master);
222
223 return 0;
ca10883e
DS
224}
225
226static void
227babel_fail(void)
228{
229 exit(1);
230}
231
232/* initialize random value, and set 'babel_now' by the way. */
233static void
234babel_init_random(void)
235{
236 gettime(&babel_now);
237 int rc;
238 unsigned int seed;
239
240 rc = read_random_bytes(&seed, sizeof(seed));
241 if(rc < 0) {
450971aa 242 flog_err_sys(EC_LIB_SYSTEM_CALL, "read(random): %s",
f135ba52 243 safe_strerror(errno));
ca10883e
DS
244 seed = 42;
245 }
246
247 seed ^= (babel_now.tv_sec ^ babel_now.tv_usec);
248 srandom(seed);
249}
250
251/*
252 close fd, and replace it by "/dev/null"
253 exit if error
254 */
255static void
256babel_replace_by_null(int fd)
257{
258 int fd_null;
259 int rc;
260
261 fd_null = open("/dev/null", O_RDONLY);
262 if(fd_null < 0) {
450971aa 263 flog_err_sys(EC_LIB_SYSTEM_CALL, "open(null): %s", safe_strerror(errno));
ca10883e
DS
264 exit(1);
265 }
266
267 rc = dup2(fd_null, fd);
268 if(rc < 0) {
450971aa 269 flog_err_sys(EC_LIB_SYSTEM_CALL, "dup2(null, 0): %s",
f135ba52 270 safe_strerror(errno));
ca10883e
DS
271 exit(1);
272 }
273
274 close(fd_null);
275}
276
277/*
278 Load the state file: check last babeld's running state, usefull in case of
279 "/etc/init.d/babeld restart"
280 */
281void
282babel_load_state_file(void)
283{
284 int fd;
285 int rc;
286
287 fd = open(state_file, O_RDONLY);
288 if(fd < 0 && errno != ENOENT)
450971aa 289 flog_err_sys(EC_LIB_SYSTEM_CALL, "open(babel-state: %s)",
f135ba52 290 safe_strerror(errno));
ca10883e
DS
291 rc = unlink(state_file);
292 if(fd >= 0 && rc < 0) {
450971aa 293 flog_err_sys(EC_LIB_SYSTEM_CALL, "unlink(babel-state): %s",
f135ba52 294 safe_strerror(errno));
ca10883e 295 /* If we couldn't unlink it, it's probably stale. */
c31a793b 296 goto fini;
ca10883e
DS
297 }
298 if(fd >= 0) {
299 char buf[100];
300 char buf2[100];
301 int s;
302 long t;
303 rc = read(fd, buf, 99);
304 if(rc < 0) {
450971aa 305 flog_err_sys(EC_LIB_SYSTEM_CALL, "read(babel-state): %s",
f135ba52 306 safe_strerror(errno));
ca10883e
DS
307 } else {
308 buf[rc] = '\0';
309 rc = sscanf(buf, "%99s %d %ld\n", buf2, &s, &t);
310 if(rc == 3 && s >= 0 && s <= 0xFFFF) {
311 unsigned char sid[8];
312 rc = parse_eui64(buf2, sid);
313 if(rc < 0) {
5b003f31 314 flog_err(EC_BABEL_CONFIG, "Couldn't parse babel-state.");
ca10883e
DS
315 } else {
316 struct timeval realnow;
317 debugf(BABEL_DEBUG_COMMON,
318 "Got %s %d %ld from babel-state.",
319 format_eui64(sid), s, t);
320 gettimeofday(&realnow, NULL);
321 if(memcmp(sid, myid, 8) == 0)
322 myseqno = seqno_plus(s, 1);
323 else
5b003f31 324 flog_err(EC_BABEL_CONFIG,
e33b116c 325 "ID mismatch in babel-state. id=%s; old=%s",
ca10883e
DS
326 format_eui64(myid),
327 format_eui64(sid));
328 }
329 } else {
5b003f31 330 flog_err(EC_BABEL_CONFIG, "Couldn't parse babel-state.");
ca10883e
DS
331 }
332 }
c31a793b 333 goto fini;
ca10883e 334 }
c31a793b
VJ
335fini:
336 if (fd >= 0)
337 close(fd);
338 return ;
ca10883e
DS
339}
340
341static void
342babel_exit_properly(void)
343{
344 debugf(BABEL_DEBUG_COMMON, "Exiting...");
345 usleep(roughly(10000));
346 gettime(&babel_now);
347
348 /* Uninstall and flush all routes. */
349 debugf(BABEL_DEBUG_COMMON, "Uninstall routes.");
350 flush_all_routes();
351 babel_interface_close_all();
352 babel_zebra_close_connexion();
353 babel_save_state_file();
354 debugf(BABEL_DEBUG_COMMON, "Remove pid file.");
355 debugf(BABEL_DEBUG_COMMON, "Done.");
8879bd22 356 frr_fini();
ca10883e
DS
357
358 exit(0);
359}
360
361static void
362babel_save_state_file(void)
363{
364 int fd;
365 int rc;
366
367 debugf(BABEL_DEBUG_COMMON, "Save state file.");
368 fd = open(state_file, O_WRONLY | O_TRUNC | O_CREAT, 0644);
369 if(fd < 0) {
450971aa 370 flog_err_sys(EC_LIB_SYSTEM_CALL, "creat(babel-state): %s",
f135ba52 371 safe_strerror(errno));
ca10883e
DS
372 unlink(state_file);
373 } else {
374 struct timeval realnow;
375 char buf[100];
376 gettimeofday(&realnow, NULL);
377 rc = snprintf(buf, 100, "%s %d %ld\n",
378 format_eui64(myid), (int)myseqno,
379 (long)realnow.tv_sec);
380 if(rc < 0 || rc >= 100) {
5b003f31 381 flog_err(EC_BABEL_CONFIG, "write(babel-state): overflow.");
ca10883e
DS
382 unlink(state_file);
383 } else {
384 rc = write(fd, buf, rc);
385 if(rc < 0) {
5b003f31 386 flog_err(EC_BABEL_CONFIG, "write(babel-state): %s",
e33b116c 387 safe_strerror(errno));
ca10883e
DS
388 unlink(state_file);
389 }
390 fsync(fd);
391 }
392 close(fd);
393 }
394}
395
396void
397show_babel_main_configuration (struct vty *vty)
398{
181039f3 399 vty_out (vty,
cdda2010
DL
400 "state file = %s\n"
401 "configuration file = %s\n"
0437e105 402 "protocol information:\n"
cdda2010
DL
403 " multicast address = %s\n"
404 " port = %d\n"
405 "vty address = %s\n"
406 "vty port = %d\n"
407 "id = %s\n"
181039f3 408 "kernel_metric = %d\n",
cdda2010 409 state_file,
f714218e 410 babeld_di.config_file ? babeld_di.config_file : babel_config_default,
cdda2010
DL
411 format_address(protocol_group),
412 protocol_port,
ca10883e 413 babel_vty_addr ? babel_vty_addr : "None",
cdda2010
DL
414 babel_vty_port,
415 format_eui64(myid),
96ade3ed 416 kernel_metric);
ca10883e 417}