]> git.proxmox.com Git - mirror_frr.git/blob - babeld/babel_main.c
Merge pull request #12715 from opensourcerouting/fix/contribution_guid_squash_random_...
[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 "lib/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_exit_properly(void);
54 static void babel_save_state_file(void);
55
56
57 struct thread_master *master; /* quagga's threads handler */
58 struct timeval babel_now; /* current time */
59
60 unsigned char myid[8]; /* unique id (mac address of an interface) */
61 int debug = 0;
62
63 int resend_delay = -1;
64
65 const unsigned char zeroes[16] = {0};
66 const unsigned char ones[16] =
67 {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
68 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
69
70 static char state_file[1024];
71
72 unsigned char protocol_group[16]; /* babel's link-local multicast address */
73 int protocol_port; /* babel's port */
74 int protocol_socket = -1; /* socket: communicate with others babeld */
75
76 static const char babel_config_default[] = SYSCONFDIR BABEL_DEFAULT_CONFIG;
77 static char *babel_vty_addr = NULL;
78 static int babel_vty_port = BABEL_VTY_PORT;
79
80 /* babeld privileges */
81 static zebra_capabilities_t _caps_p [] =
82 {
83 ZCAP_NET_RAW,
84 ZCAP_BIND
85 };
86
87 struct zebra_privs_t babeld_privs =
88 {
89 #if defined(FRR_USER)
90 .user = FRR_USER,
91 #endif
92 #if defined FRR_GROUP
93 .group = FRR_GROUP,
94 #endif
95 #ifdef VTY_GROUP
96 .vty_group = VTY_GROUP,
97 #endif
98 .caps_p = _caps_p,
99 .cap_num_p = array_size(_caps_p),
100 .cap_num_i = 0
101 };
102
103 static void
104 babel_sigexit(void)
105 {
106 zlog_notice("Terminating on signal");
107
108 babel_exit_properly();
109 }
110
111 static void
112 babel_sigusr1 (void)
113 {
114 zlog_rotate ();
115 }
116
117 static struct frr_signal_t babel_signals[] =
118 {
119 {
120 .signal = SIGUSR1,
121 .handler = &babel_sigusr1,
122 },
123 {
124 .signal = SIGINT,
125 .handler = &babel_sigexit,
126 },
127 {
128 .signal = SIGTERM,
129 .handler = &babel_sigexit,
130 },
131 };
132
133 struct option longopts[] =
134 {
135 { 0 }
136 };
137
138 static const struct frr_yang_module_info *const babeld_yang_modules[] = {
139 &frr_filter_info,
140 &frr_interface_info,
141 &frr_vrf_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 }
187 }
188
189 snprintf(state_file, sizeof(state_file), "%s/%s",
190 frr_vtydir, "babel-state");
191
192 /* create the threads handler */
193 master = frr_init ();
194
195 /* Library inits. */
196 babel_error_init();
197
198 resend_delay = BABEL_DEFAULT_RESEND_DELAY;
199 change_smoothing_half_life(BABEL_DEFAULT_SMOOTHING_HALF_LIFE);
200
201 /* init some quagga's dependencies, and babeld's commands */
202 if_zapi_callbacks(babel_ifp_create, babel_ifp_up,
203 babel_ifp_down, babel_ifp_destroy);
204 babeld_quagga_init();
205 /* init zebra client's structure and it's commands */
206 /* this replace kernel_setup && kernel_setup_socket */
207 babelz_zebra_init ();
208
209 /* init buffer */
210 rc = resize_receive_buffer(1500);
211 if(rc < 0)
212 babel_fail();
213
214 schedule_neighbours_check(5000, 1);
215
216 frr_config_fork();
217 frr_run(master);
218
219 return 0;
220 }
221
222 static void
223 babel_fail(void)
224 {
225 exit(1);
226 }
227
228 /* initialize random value, and set 'babel_now' by the way. */
229 static void
230 babel_init_random(void)
231 {
232 gettime(&babel_now);
233 int rc;
234 unsigned int seed;
235
236 rc = read_random_bytes(&seed, sizeof(seed));
237 if(rc < 0) {
238 flog_err_sys(EC_LIB_SYSTEM_CALL, "read(random): %s",
239 safe_strerror(errno));
240 seed = 42;
241 }
242
243 seed ^= (babel_now.tv_sec ^ babel_now.tv_usec);
244 srandom(seed);
245 }
246
247 /*
248 Load the state file: check last babeld's running state, usefull in case of
249 "/etc/init.d/babeld restart"
250 */
251 void
252 babel_load_state_file(void)
253 {
254 int fd;
255 int rc;
256
257 fd = open(state_file, O_RDONLY);
258 if(fd < 0 && errno != ENOENT)
259 flog_err_sys(EC_LIB_SYSTEM_CALL, "open(babel-state: %s)",
260 safe_strerror(errno));
261 rc = unlink(state_file);
262 if(fd >= 0 && rc < 0) {
263 flog_err_sys(EC_LIB_SYSTEM_CALL, "unlink(babel-state): %s",
264 safe_strerror(errno));
265 /* If we couldn't unlink it, it's probably stale. */
266 goto fini;
267 }
268 if(fd >= 0) {
269 char buf[100];
270 char buf2[100];
271 int s;
272 long t;
273 rc = read(fd, buf, 99);
274 if(rc < 0) {
275 flog_err_sys(EC_LIB_SYSTEM_CALL, "read(babel-state): %s",
276 safe_strerror(errno));
277 } else {
278 buf[rc] = '\0';
279 rc = sscanf(buf, "%99s %d %ld\n", buf2, &s, &t);
280 if(rc == 3 && s >= 0 && s <= 0xFFFF) {
281 unsigned char sid[8];
282 rc = parse_eui64(buf2, sid);
283 if(rc < 0) {
284 flog_err(EC_BABEL_CONFIG, "Couldn't parse babel-state.");
285 } else {
286 struct timeval realnow;
287 debugf(BABEL_DEBUG_COMMON,
288 "Got %s %d %ld from babel-state.",
289 format_eui64(sid), s, t);
290 gettimeofday(&realnow, NULL);
291 if(memcmp(sid, myid, 8) == 0)
292 myseqno = seqno_plus(s, 1);
293 else
294 flog_err(EC_BABEL_CONFIG,
295 "ID mismatch in babel-state. id=%s; old=%s",
296 format_eui64(myid),
297 format_eui64(sid));
298 }
299 } else {
300 flog_err(EC_BABEL_CONFIG, "Couldn't parse babel-state.");
301 }
302 }
303 goto fini;
304 }
305 fini:
306 if (fd >= 0)
307 close(fd);
308 return ;
309 }
310
311 static void
312 babel_exit_properly(void)
313 {
314 debugf(BABEL_DEBUG_COMMON, "Exiting...");
315 usleep(roughly(10000));
316 gettime(&babel_now);
317
318 /* Uninstall and flush all routes. */
319 debugf(BABEL_DEBUG_COMMON, "Uninstall routes.");
320 flush_all_routes();
321 babel_interface_close_all();
322 babel_zebra_close_connexion();
323 babel_save_state_file();
324 debugf(BABEL_DEBUG_COMMON, "Remove pid file.");
325 debugf(BABEL_DEBUG_COMMON, "Done.");
326 frr_fini();
327
328 exit(0);
329 }
330
331 static void
332 babel_save_state_file(void)
333 {
334 int fd;
335 int rc;
336
337 debugf(BABEL_DEBUG_COMMON, "Save state file.");
338 fd = open(state_file, O_WRONLY | O_TRUNC | O_CREAT, 0644);
339 if(fd < 0) {
340 flog_err_sys(EC_LIB_SYSTEM_CALL, "creat(babel-state): %s",
341 safe_strerror(errno));
342 unlink(state_file);
343 } else {
344 struct timeval realnow;
345 char buf[100];
346 gettimeofday(&realnow, NULL);
347 rc = snprintf(buf, 100, "%s %d %ld\n",
348 format_eui64(myid), (int)myseqno,
349 (long)realnow.tv_sec);
350 if(rc < 0 || rc >= 100) {
351 flog_err(EC_BABEL_CONFIG, "write(babel-state): overflow.");
352 unlink(state_file);
353 } else {
354 rc = write(fd, buf, rc);
355 if(rc < 0) {
356 flog_err(EC_BABEL_CONFIG, "write(babel-state): %s",
357 safe_strerror(errno));
358 unlink(state_file);
359 }
360 fsync(fd);
361 }
362 close(fd);
363 }
364 }
365
366 void
367 show_babel_main_configuration (struct vty *vty)
368 {
369 vty_out (vty,
370 "state file = %s\n"
371 "configuration file = %s\n"
372 "protocol information:\n"
373 " multicast address = %s\n"
374 " port = %d\n"
375 "vty address = %s\n"
376 "vty port = %d\n"
377 "id = %s\n"
378 "kernel_metric = %d\n",
379 state_file,
380 babeld_di.config_file ? babeld_di.config_file : babel_config_default,
381 format_address(protocol_group),
382 protocol_port,
383 babel_vty_addr ? babel_vty_addr : "None",
384 babel_vty_port,
385 format_eui64(myid),
386 kernel_metric);
387 }