]> git.proxmox.com Git - mirror_frr.git/blame - babeld/babel_main.c
*: 6.0.3 release
[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
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) {
09c866e3 228 flog_err_sys(LIB_ERR_SYSTEM_CALL, "read(random): %s",
f135ba52 229 safe_strerror(errno));
ca10883e
DS
230 seed = 42;
231 }
232
233 seed ^= (babel_now.tv_sec ^ babel_now.tv_usec);
234 srandom(seed);
235}
236
237/*
238 close fd, and replace it by "/dev/null"
239 exit if error
240 */
241static void
242babel_replace_by_null(int fd)
243{
244 int fd_null;
245 int rc;
246
247 fd_null = open("/dev/null", O_RDONLY);
248 if(fd_null < 0) {
09c866e3 249 flog_err_sys(LIB_ERR_SYSTEM_CALL, "open(null): %s", safe_strerror(errno));
ca10883e
DS
250 exit(1);
251 }
252
253 rc = dup2(fd_null, fd);
254 if(rc < 0) {
09c866e3 255 flog_err_sys(LIB_ERR_SYSTEM_CALL, "dup2(null, 0): %s",
f135ba52 256 safe_strerror(errno));
ca10883e
DS
257 exit(1);
258 }
259
260 close(fd_null);
261}
262
263/*
264 Load the state file: check last babeld's running state, usefull in case of
265 "/etc/init.d/babeld restart"
266 */
267void
268babel_load_state_file(void)
269{
270 int fd;
271 int rc;
272
273 fd = open(state_file, O_RDONLY);
274 if(fd < 0 && errno != ENOENT)
09c866e3 275 flog_err_sys(LIB_ERR_SYSTEM_CALL, "open(babel-state: %s)",
f135ba52 276 safe_strerror(errno));
ca10883e
DS
277 rc = unlink(state_file);
278 if(fd >= 0 && rc < 0) {
09c866e3 279 flog_err_sys(LIB_ERR_SYSTEM_CALL, "unlink(babel-state): %s",
f135ba52 280 safe_strerror(errno));
ca10883e 281 /* If we couldn't unlink it, it's probably stale. */
c31a793b 282 goto fini;
ca10883e
DS
283 }
284 if(fd >= 0) {
285 char buf[100];
286 char buf2[100];
287 int s;
288 long t;
289 rc = read(fd, buf, 99);
290 if(rc < 0) {
09c866e3 291 flog_err_sys(LIB_ERR_SYSTEM_CALL, "read(babel-state): %s",
f135ba52 292 safe_strerror(errno));
ca10883e
DS
293 } else {
294 buf[rc] = '\0';
295 rc = sscanf(buf, "%99s %d %ld\n", buf2, &s, &t);
296 if(rc == 3 && s >= 0 && s <= 0xFFFF) {
297 unsigned char sid[8];
298 rc = parse_eui64(buf2, sid);
299 if(rc < 0) {
af4c2728 300 flog_err(BABEL_ERR_CONFIG, "Couldn't parse babel-state.");
ca10883e
DS
301 } else {
302 struct timeval realnow;
303 debugf(BABEL_DEBUG_COMMON,
304 "Got %s %d %ld from babel-state.",
305 format_eui64(sid), s, t);
306 gettimeofday(&realnow, NULL);
307 if(memcmp(sid, myid, 8) == 0)
308 myseqno = seqno_plus(s, 1);
309 else
af4c2728 310 flog_err(BABEL_ERR_CONFIG,
e33b116c 311 "ID mismatch in babel-state. id=%s; old=%s",
ca10883e
DS
312 format_eui64(myid),
313 format_eui64(sid));
314 }
315 } else {
af4c2728 316 flog_err(BABEL_ERR_CONFIG, "Couldn't parse babel-state.");
ca10883e
DS
317 }
318 }
c31a793b 319 goto fini;
ca10883e 320 }
c31a793b
VJ
321fini:
322 if (fd >= 0)
323 close(fd);
324 return ;
ca10883e
DS
325}
326
327static void
328babel_exit_properly(void)
329{
330 debugf(BABEL_DEBUG_COMMON, "Exiting...");
331 usleep(roughly(10000));
332 gettime(&babel_now);
333
334 /* Uninstall and flush all routes. */
335 debugf(BABEL_DEBUG_COMMON, "Uninstall routes.");
336 flush_all_routes();
337 babel_interface_close_all();
338 babel_zebra_close_connexion();
339 babel_save_state_file();
340 debugf(BABEL_DEBUG_COMMON, "Remove pid file.");
341 debugf(BABEL_DEBUG_COMMON, "Done.");
8879bd22 342 frr_fini();
ca10883e
DS
343
344 exit(0);
345}
346
347static void
348babel_save_state_file(void)
349{
350 int fd;
351 int rc;
352
353 debugf(BABEL_DEBUG_COMMON, "Save state file.");
354 fd = open(state_file, O_WRONLY | O_TRUNC | O_CREAT, 0644);
355 if(fd < 0) {
09c866e3 356 flog_err_sys(LIB_ERR_SYSTEM_CALL, "creat(babel-state): %s",
f135ba52 357 safe_strerror(errno));
ca10883e
DS
358 unlink(state_file);
359 } else {
360 struct timeval realnow;
361 char buf[100];
362 gettimeofday(&realnow, NULL);
363 rc = snprintf(buf, 100, "%s %d %ld\n",
364 format_eui64(myid), (int)myseqno,
365 (long)realnow.tv_sec);
366 if(rc < 0 || rc >= 100) {
af4c2728 367 flog_err(BABEL_ERR_CONFIG, "write(babel-state): overflow.");
ca10883e
DS
368 unlink(state_file);
369 } else {
370 rc = write(fd, buf, rc);
371 if(rc < 0) {
af4c2728 372 flog_err(BABEL_ERR_CONFIG, "write(babel-state): %s",
e33b116c 373 safe_strerror(errno));
ca10883e
DS
374 unlink(state_file);
375 }
376 fsync(fd);
377 }
378 close(fd);
379 }
380}
381
382void
383show_babel_main_configuration (struct vty *vty)
384{
181039f3 385 vty_out (vty,
cdda2010
DL
386 "state file = %s\n"
387 "configuration file = %s\n"
4e69658c 388 "protocol information:\n"
cdda2010
DL
389 " multicast address = %s\n"
390 " port = %d\n"
391 "vty address = %s\n"
392 "vty port = %d\n"
393 "id = %s\n"
181039f3 394 "kernel_metric = %d\n",
cdda2010 395 state_file,
f714218e 396 babeld_di.config_file ? babeld_di.config_file : babel_config_default,
cdda2010
DL
397 format_address(protocol_group),
398 protocol_port,
ca10883e 399 babel_vty_addr ? babel_vty_addr : "None",
cdda2010
DL
400 babel_vty_port,
401 format_eui64(myid),
96ade3ed 402 kernel_metric);
ca10883e 403}