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