]> git.proxmox.com Git - mirror_frr.git/blame - babeld/babel_main.c
Merge branch 'master' into bfd-final
[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"
36
37#include "babel_main.h"
38#include "babeld.h"
39#include "util.h"
40#include "kernel.h"
41#include "babel_interface.h"
42#include "neighbour.h"
43#include "route.h"
44#include "xroute.h"
45#include "message.h"
46#include "resend.h"
47#include "babel_zebra.h"
48
ca10883e
DS
49static void babel_fail(void);
50static void babel_init_random(void);
51static void babel_replace_by_null(int fd);
52static void babel_exit_properly(void);
53static void babel_save_state_file(void);
54
55
56struct thread_master *master; /* quagga's threads handler */
57struct timeval babel_now; /* current time */
58
59unsigned char myid[8]; /* unique id (mac address of an interface) */
60int debug = 0;
61
62int resend_delay = -1;
63
64const unsigned char zeroes[16] = {0};
65const unsigned char ones[16] =
66 {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
67 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
68
69static const char *state_file = DAEMON_VTY_DIR "/babel-state";
70
71unsigned char protocol_group[16]; /* babel's link-local multicast address */
72int protocol_port; /* babel's port */
73int protocol_socket = -1; /* socket: communicate with others babeld */
74
75static char babel_config_default[] = SYSCONFDIR BABEL_DEFAULT_CONFIG;
ca10883e
DS
76static char *babel_vty_addr = NULL;
77static int babel_vty_port = BABEL_VTY_PORT;
78
79/* babeld privileges */
80static zebra_capabilities_t _caps_p [] =
81{
82 ZCAP_NET_RAW,
83 ZCAP_BIND
84};
900b8c58 85
346526cc 86struct zebra_privs_t babeld_privs =
ca10883e 87{
dd329373
DS
88#if defined(FRR_USER)
89 .user = FRR_USER,
ca10883e 90#endif
dd329373
DS
91#if defined FRR_GROUP
92 .group = FRR_GROUP,
ca10883e
DS
93#endif
94#ifdef VTY_GROUP
95 .vty_group = VTY_GROUP,
96#endif
97 .caps_p = _caps_p,
900b8c58 98 .cap_num_p = array_size(_caps_p),
ca10883e
DS
99 .cap_num_i = 0
100};
101
102static void
103babel_sigexit(void)
104{
105 zlog_notice("Terminating on signal");
106
107 babel_exit_properly();
108}
109
110static void
111babel_sigusr1 (void)
112{
113 zlog_rotate ();
114}
115
116static struct quagga_signal_t babel_signals[] =
117 {
118 {
119 .signal = SIGUSR1,
120 .handler = &babel_sigusr1,
121 },
122 {
123 .signal = SIGINT,
124 .handler = &babel_sigexit,
125 },
126 {
127 .signal = SIGTERM,
128 .handler = &babel_sigexit,
129 },
130 };
131
132struct option longopts[] =
133 {
134 { 0 }
135 };
136
137FRR_DAEMON_INFO(babeld, BABELD,
138 .vty_port = BABEL_VTY_PORT,
139 .proghelp = "Implementation of the BABEL routing protocol.",
140
141 .signals = babel_signals,
142 .n_signals = array_size(babel_signals),
143
144 .privs = &babeld_privs,
145 )
146
147int
148main(int argc, char **argv)
149{
900b8c58 150 int rc;
ca10883e 151
900b8c58
DS
152 frr_preinit (&babeld_di, argc, argv);
153 frr_opt_add ("", longopts, "");
ca10883e
DS
154
155 babel_init_random();
156
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;
160
161 /* get options */
162 while(1) {
163 int opt;
164
165 opt = frr_getopt (argc, argv, NULL);
166
167 if (opt == EOF)
168 break;
169
170 switch (opt)
171 {
172 case 0:
173 break;
174 default:
175 frr_help_exit (1);
176 break;
177 }
178 }
179
180 /* create the threads handler */
900b8c58 181 master = frr_init ();
ca10883e
DS
182
183 /* Library inits. */
184 zprivs_init (&babeld_privs);
185 cmd_init (1);
186 vty_init (master);
187
188 resend_delay = BABEL_DEFAULT_RESEND_DELAY;
189 change_smoothing_half_life(BABEL_DEFAULT_SMOOTHING_HALF_LIFE);
190
191 babel_replace_by_null(STDIN_FILENO);
192
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 ();
198
ca10883e
DS
199 /* init buffer */
200 rc = resize_receive_buffer(1500);
201 if(rc < 0)
202 babel_fail();
203
204 schedule_neighbours_check(5000, 1);
205
900b8c58
DS
206 frr_config_fork();
207 frr_run(master);
208
209 return 0;
ca10883e
DS
210}
211
212static void
213babel_fail(void)
214{
215 exit(1);
216}
217
218/* initialize random value, and set 'babel_now' by the way. */
219static void
220babel_init_random(void)
221{
222 gettime(&babel_now);
223 int rc;
224 unsigned int seed;
225
226 rc = read_random_bytes(&seed, sizeof(seed));
227 if(rc < 0) {
228 zlog_err("read(random): %s", safe_strerror(errno));
229 seed = 42;
230 }
231
232 seed ^= (babel_now.tv_sec ^ babel_now.tv_usec);
233 srandom(seed);
234}
235
236/*
237 close fd, and replace it by "/dev/null"
238 exit if error
239 */
240static void
241babel_replace_by_null(int fd)
242{
243 int fd_null;
244 int rc;
245
246 fd_null = open("/dev/null", O_RDONLY);
247 if(fd_null < 0) {
248 zlog_err("open(null): %s", safe_strerror(errno));
249 exit(1);
250 }
251
252 rc = dup2(fd_null, fd);
253 if(rc < 0) {
254 zlog_err("dup2(null, 0): %s", safe_strerror(errno));
255 exit(1);
256 }
257
258 close(fd_null);
259}
260
261/*
262 Load the state file: check last babeld's running state, usefull in case of
263 "/etc/init.d/babeld restart"
264 */
265void
266babel_load_state_file(void)
267{
268 int fd;
269 int rc;
270
271 fd = open(state_file, O_RDONLY);
272 if(fd < 0 && errno != ENOENT)
273 zlog_err("open(babel-state: %s)", safe_strerror(errno));
274 rc = unlink(state_file);
275 if(fd >= 0 && rc < 0) {
276 zlog_err("unlink(babel-state): %s", safe_strerror(errno));
277 /* If we couldn't unlink it, it's probably stale. */
c31a793b 278 goto fini;
ca10883e
DS
279 }
280 if(fd >= 0) {
281 char buf[100];
282 char buf2[100];
283 int s;
284 long t;
285 rc = read(fd, buf, 99);
286 if(rc < 0) {
287 zlog_err("read(babel-state): %s", safe_strerror(errno));
288 } else {
289 buf[rc] = '\0';
290 rc = sscanf(buf, "%99s %d %ld\n", buf2, &s, &t);
291 if(rc == 3 && s >= 0 && s <= 0xFFFF) {
292 unsigned char sid[8];
293 rc = parse_eui64(buf2, sid);
294 if(rc < 0) {
295 zlog_err("Couldn't parse babel-state.");
296 } else {
297 struct timeval realnow;
298 debugf(BABEL_DEBUG_COMMON,
299 "Got %s %d %ld from babel-state.",
300 format_eui64(sid), s, t);
301 gettimeofday(&realnow, NULL);
302 if(memcmp(sid, myid, 8) == 0)
303 myseqno = seqno_plus(s, 1);
304 else
305 zlog_err("ID mismatch in babel-state. id=%s; old=%s",
306 format_eui64(myid),
307 format_eui64(sid));
308 }
309 } else {
310 zlog_err("Couldn't parse babel-state.");
311 }
312 }
c31a793b 313 goto fini;
ca10883e 314 }
c31a793b
VJ
315fini:
316 if (fd >= 0)
317 close(fd);
318 return ;
ca10883e
DS
319}
320
321static void
322babel_exit_properly(void)
323{
324 debugf(BABEL_DEBUG_COMMON, "Exiting...");
325 usleep(roughly(10000));
326 gettime(&babel_now);
327
328 /* Uninstall and flush all routes. */
329 debugf(BABEL_DEBUG_COMMON, "Uninstall routes.");
330 flush_all_routes();
331 babel_interface_close_all();
332 babel_zebra_close_connexion();
333 babel_save_state_file();
334 debugf(BABEL_DEBUG_COMMON, "Remove pid file.");
335 debugf(BABEL_DEBUG_COMMON, "Done.");
8879bd22 336 frr_fini();
ca10883e
DS
337
338 exit(0);
339}
340
341static void
342babel_save_state_file(void)
343{
344 int fd;
345 int rc;
346
347 debugf(BABEL_DEBUG_COMMON, "Save state file.");
348 fd = open(state_file, O_WRONLY | O_TRUNC | O_CREAT, 0644);
349 if(fd < 0) {
350 zlog_err("creat(babel-state): %s", safe_strerror(errno));
351 unlink(state_file);
352 } else {
353 struct timeval realnow;
354 char buf[100];
355 gettimeofday(&realnow, NULL);
356 rc = snprintf(buf, 100, "%s %d %ld\n",
357 format_eui64(myid), (int)myseqno,
358 (long)realnow.tv_sec);
359 if(rc < 0 || rc >= 100) {
360 zlog_err("write(babel-state): overflow.");
361 unlink(state_file);
362 } else {
363 rc = write(fd, buf, rc);
364 if(rc < 0) {
365 zlog_err("write(babel-state): %s", safe_strerror(errno));
366 unlink(state_file);
367 }
368 fsync(fd);
369 }
370 close(fd);
371 }
372}
373
374void
375show_babel_main_configuration (struct vty *vty)
376{
181039f3 377 vty_out (vty,
cdda2010
DL
378 "state file = %s\n"
379 "configuration file = %s\n"
380 "protocol informations:\n"
381 " multicast address = %s\n"
382 " port = %d\n"
383 "vty address = %s\n"
384 "vty port = %d\n"
385 "id = %s\n"
181039f3 386 "kernel_metric = %d\n",
cdda2010 387 state_file,
f714218e 388 babeld_di.config_file ? babeld_di.config_file : babel_config_default,
cdda2010
DL
389 format_address(protocol_group),
390 protocol_port,
ca10883e 391 babel_vty_addr ? babel_vty_addr : "None",
cdda2010
DL
392 babel_vty_port,
393 format_eui64(myid),
96ade3ed 394 kernel_metric);
ca10883e 395}