]> git.proxmox.com Git - mirror_frr.git/blob - babeld/babel_main.c
Pim bug fixes (#4519)
[mirror_frr.git] / babeld / babel_main.c
1 /*
2 Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
3
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 THE 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 #include "lib_errors.h"
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"
49 #include "babel_errors.h"
50
51 static void babel_fail(void);
52 static void babel_init_random(void);
53 static void babel_replace_by_null(int fd);
54 static void babel_exit_properly(void);
55 static void babel_save_state_file(void);
56
57
58 struct thread_master *master; /* quagga's threads handler */
59 struct timeval babel_now; /* current time */
60
61 unsigned char myid[8]; /* unique id (mac address of an interface) */
62 int debug = 0;
63
64 int resend_delay = -1;
65
66 const unsigned char zeroes[16] = {0};
67 const unsigned char ones[16] =
68 {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
69 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
70
71 static char state_file[1024];
72
73 unsigned char protocol_group[16]; /* babel's link-local multicast address */
74 int protocol_port; /* babel's port */
75 int protocol_socket = -1; /* socket: communicate with others babeld */
76
77 static char babel_config_default[] = SYSCONFDIR BABEL_DEFAULT_CONFIG;
78 static char *babel_vty_addr = NULL;
79 static int babel_vty_port = BABEL_VTY_PORT;
80
81 /* babeld privileges */
82 static zebra_capabilities_t _caps_p [] =
83 {
84 ZCAP_NET_RAW,
85 ZCAP_BIND
86 };
87
88 struct zebra_privs_t babeld_privs =
89 {
90 #if defined(FRR_USER)
91 .user = FRR_USER,
92 #endif
93 #if defined FRR_GROUP
94 .group = FRR_GROUP,
95 #endif
96 #ifdef VTY_GROUP
97 .vty_group = VTY_GROUP,
98 #endif
99 .caps_p = _caps_p,
100 .cap_num_p = array_size(_caps_p),
101 .cap_num_i = 0
102 };
103
104 static void
105 babel_sigexit(void)
106 {
107 zlog_notice("Terminating on signal");
108
109 babel_exit_properly();
110 }
111
112 static void
113 babel_sigusr1 (void)
114 {
115 zlog_rotate ();
116 }
117
118 static 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
134 struct option longopts[] =
135 {
136 { 0 }
137 };
138
139 static const struct frr_yang_module_info *babeld_yang_modules[] =
140 {
141 &frr_interface_info,
142 };
143
144 FRR_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,
152
153 .yang_modules = babeld_yang_modules,
154 .n_yang_modules = array_size(babeld_yang_modules),
155 )
156
157 int
158 main(int argc, char **argv)
159 {
160 int rc;
161
162 frr_preinit (&babeld_di, argc, argv);
163 frr_opt_add ("", longopts, "");
164
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 snprintf(state_file, sizeof(state_file), "%s/%s",
191 frr_vtydir, "babel-state");
192
193 /* create the threads handler */
194 master = frr_init ();
195
196 /* Library inits. */
197 babel_error_init();
198
199 resend_delay = BABEL_DEFAULT_RESEND_DELAY;
200 change_smoothing_half_life(BABEL_DEFAULT_SMOOTHING_HALF_LIFE);
201
202 babel_replace_by_null(STDIN_FILENO);
203
204 /* init some quagga's dependencies, and babeld's commands */
205 babeld_quagga_init();
206 /* init zebra client's structure and it's commands */
207 /* this replace kernel_setup && kernel_setup_socket */
208 babelz_zebra_init ();
209
210 /* init buffer */
211 rc = resize_receive_buffer(1500);
212 if(rc < 0)
213 babel_fail();
214
215 schedule_neighbours_check(5000, 1);
216
217 frr_config_fork();
218 frr_run(master);
219
220 return 0;
221 }
222
223 static void
224 babel_fail(void)
225 {
226 exit(1);
227 }
228
229 /* initialize random value, and set 'babel_now' by the way. */
230 static void
231 babel_init_random(void)
232 {
233 gettime(&babel_now);
234 int rc;
235 unsigned int seed;
236
237 rc = read_random_bytes(&seed, sizeof(seed));
238 if(rc < 0) {
239 flog_err_sys(EC_LIB_SYSTEM_CALL, "read(random): %s",
240 safe_strerror(errno));
241 seed = 42;
242 }
243
244 seed ^= (babel_now.tv_sec ^ babel_now.tv_usec);
245 srandom(seed);
246 }
247
248 /*
249 close fd, and replace it by "/dev/null"
250 exit if error
251 */
252 static void
253 babel_replace_by_null(int fd)
254 {
255 int fd_null;
256 int rc;
257
258 fd_null = open("/dev/null", O_RDONLY);
259 if(fd_null < 0) {
260 flog_err_sys(EC_LIB_SYSTEM_CALL, "open(null): %s", safe_strerror(errno));
261 exit(1);
262 }
263
264 rc = dup2(fd_null, fd);
265 if(rc < 0) {
266 flog_err_sys(EC_LIB_SYSTEM_CALL, "dup2(null, 0): %s",
267 safe_strerror(errno));
268 exit(1);
269 }
270
271 close(fd_null);
272 }
273
274 /*
275 Load the state file: check last babeld's running state, usefull in case of
276 "/etc/init.d/babeld restart"
277 */
278 void
279 babel_load_state_file(void)
280 {
281 int fd;
282 int rc;
283
284 fd = open(state_file, O_RDONLY);
285 if(fd < 0 && errno != ENOENT)
286 flog_err_sys(EC_LIB_SYSTEM_CALL, "open(babel-state: %s)",
287 safe_strerror(errno));
288 rc = unlink(state_file);
289 if(fd >= 0 && rc < 0) {
290 flog_err_sys(EC_LIB_SYSTEM_CALL, "unlink(babel-state): %s",
291 safe_strerror(errno));
292 /* If we couldn't unlink it, it's probably stale. */
293 goto fini;
294 }
295 if(fd >= 0) {
296 char buf[100];
297 char buf2[100];
298 int s;
299 long t;
300 rc = read(fd, buf, 99);
301 if(rc < 0) {
302 flog_err_sys(EC_LIB_SYSTEM_CALL, "read(babel-state): %s",
303 safe_strerror(errno));
304 } else {
305 buf[rc] = '\0';
306 rc = sscanf(buf, "%99s %d %ld\n", buf2, &s, &t);
307 if(rc == 3 && s >= 0 && s <= 0xFFFF) {
308 unsigned char sid[8];
309 rc = parse_eui64(buf2, sid);
310 if(rc < 0) {
311 flog_err(EC_BABEL_CONFIG, "Couldn't parse babel-state.");
312 } else {
313 struct timeval realnow;
314 debugf(BABEL_DEBUG_COMMON,
315 "Got %s %d %ld from babel-state.",
316 format_eui64(sid), s, t);
317 gettimeofday(&realnow, NULL);
318 if(memcmp(sid, myid, 8) == 0)
319 myseqno = seqno_plus(s, 1);
320 else
321 flog_err(EC_BABEL_CONFIG,
322 "ID mismatch in babel-state. id=%s; old=%s",
323 format_eui64(myid),
324 format_eui64(sid));
325 }
326 } else {
327 flog_err(EC_BABEL_CONFIG, "Couldn't parse babel-state.");
328 }
329 }
330 goto fini;
331 }
332 fini:
333 if (fd >= 0)
334 close(fd);
335 return ;
336 }
337
338 static void
339 babel_exit_properly(void)
340 {
341 debugf(BABEL_DEBUG_COMMON, "Exiting...");
342 usleep(roughly(10000));
343 gettime(&babel_now);
344
345 /* Uninstall and flush all routes. */
346 debugf(BABEL_DEBUG_COMMON, "Uninstall routes.");
347 flush_all_routes();
348 babel_interface_close_all();
349 babel_zebra_close_connexion();
350 babel_save_state_file();
351 debugf(BABEL_DEBUG_COMMON, "Remove pid file.");
352 debugf(BABEL_DEBUG_COMMON, "Done.");
353 frr_fini();
354
355 exit(0);
356 }
357
358 static void
359 babel_save_state_file(void)
360 {
361 int fd;
362 int rc;
363
364 debugf(BABEL_DEBUG_COMMON, "Save state file.");
365 fd = open(state_file, O_WRONLY | O_TRUNC | O_CREAT, 0644);
366 if(fd < 0) {
367 flog_err_sys(EC_LIB_SYSTEM_CALL, "creat(babel-state): %s",
368 safe_strerror(errno));
369 unlink(state_file);
370 } else {
371 struct timeval realnow;
372 char buf[100];
373 gettimeofday(&realnow, NULL);
374 rc = snprintf(buf, 100, "%s %d %ld\n",
375 format_eui64(myid), (int)myseqno,
376 (long)realnow.tv_sec);
377 if(rc < 0 || rc >= 100) {
378 flog_err(EC_BABEL_CONFIG, "write(babel-state): overflow.");
379 unlink(state_file);
380 } else {
381 rc = write(fd, buf, rc);
382 if(rc < 0) {
383 flog_err(EC_BABEL_CONFIG, "write(babel-state): %s",
384 safe_strerror(errno));
385 unlink(state_file);
386 }
387 fsync(fd);
388 }
389 close(fd);
390 }
391 }
392
393 void
394 show_babel_main_configuration (struct vty *vty)
395 {
396 vty_out (vty,
397 "state file = %s\n"
398 "configuration file = %s\n"
399 "protocol information:\n"
400 " multicast address = %s\n"
401 " port = %d\n"
402 "vty address = %s\n"
403 "vty port = %d\n"
404 "id = %s\n"
405 "kernel_metric = %d\n",
406 state_file,
407 babeld_di.config_file ? babeld_di.config_file : babel_config_default,
408 format_address(protocol_group),
409 protocol_port,
410 babel_vty_addr ? babel_vty_addr : "None",
411 babel_vty_port,
412 format_eui64(myid),
413 kernel_metric);
414 }