]> git.proxmox.com Git - mirror_frr.git/blob - babeld/babel_main.c
Merge pull request #13206 from opensourcerouting/fix/docker_build_alpine_protobuf
[mirror_frr.git] / babeld / babel_main.c
1 // SPDX-License-Identifier: MIT
2 /*
3 Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
4 */
5
6 /* include zebra library */
7 #include <zebra.h>
8 #include "getopt.h"
9 #include "if.h"
10 #include "log.h"
11 #include "frrevent.h"
12 #include "privs.h"
13 #include "sigevent.h"
14 #include "lib/version.h"
15 #include "command.h"
16 #include "vty.h"
17 #include "memory.h"
18 #include "libfrr.h"
19 #include "lib_errors.h"
20
21 #include "babel_main.h"
22 #include "babeld.h"
23 #include "util.h"
24 #include "kernel.h"
25 #include "babel_interface.h"
26 #include "neighbour.h"
27 #include "route.h"
28 #include "xroute.h"
29 #include "message.h"
30 #include "resend.h"
31 #include "babel_zebra.h"
32 #include "babel_errors.h"
33
34 static void babel_fail(void);
35 static void babel_init_random(void);
36 static void babel_exit_properly(void);
37 static void babel_save_state_file(void);
38
39
40 struct event_loop *master; /* quagga's threads handler */
41 struct timeval babel_now; /* current time */
42
43 unsigned char myid[8]; /* unique id (mac address of an interface) */
44 int debug = 0;
45
46 int resend_delay = -1;
47
48 const unsigned char zeroes[16] = {0};
49 const unsigned char ones[16] =
50 {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
51 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
52
53 static char state_file[1024];
54
55 unsigned char protocol_group[16]; /* babel's link-local multicast address */
56 int protocol_port; /* babel's port */
57 int protocol_socket = -1; /* socket: communicate with others babeld */
58
59 static const char babel_config_default[] = SYSCONFDIR BABEL_DEFAULT_CONFIG;
60 static char *babel_vty_addr = NULL;
61 static int babel_vty_port = BABEL_VTY_PORT;
62
63 /* babeld privileges */
64 static zebra_capabilities_t _caps_p [] =
65 {
66 ZCAP_NET_RAW,
67 ZCAP_BIND
68 };
69
70 struct zebra_privs_t babeld_privs =
71 {
72 #if defined(FRR_USER)
73 .user = FRR_USER,
74 #endif
75 #if defined FRR_GROUP
76 .group = FRR_GROUP,
77 #endif
78 #ifdef VTY_GROUP
79 .vty_group = VTY_GROUP,
80 #endif
81 .caps_p = _caps_p,
82 .cap_num_p = array_size(_caps_p),
83 .cap_num_i = 0
84 };
85
86 static void
87 babel_sigexit(void)
88 {
89 zlog_notice("Terminating on signal");
90
91 babel_exit_properly();
92 }
93
94 static void
95 babel_sigusr1 (void)
96 {
97 zlog_rotate ();
98 }
99
100 static struct frr_signal_t babel_signals[] =
101 {
102 {
103 .signal = SIGUSR1,
104 .handler = &babel_sigusr1,
105 },
106 {
107 .signal = SIGINT,
108 .handler = &babel_sigexit,
109 },
110 {
111 .signal = SIGTERM,
112 .handler = &babel_sigexit,
113 },
114 };
115
116 struct option longopts[] =
117 {
118 { 0 }
119 };
120
121 static const struct frr_yang_module_info *const babeld_yang_modules[] = {
122 &frr_filter_info,
123 &frr_interface_info,
124 &frr_vrf_info,
125 };
126
127 FRR_DAEMON_INFO(babeld, BABELD,
128 .vty_port = BABEL_VTY_PORT,
129 .proghelp = "Implementation of the BABEL routing protocol.",
130
131 .signals = babel_signals,
132 .n_signals = array_size(babel_signals),
133
134 .privs = &babeld_privs,
135
136 .yang_modules = babeld_yang_modules,
137 .n_yang_modules = array_size(babeld_yang_modules),
138 );
139
140 int
141 main(int argc, char **argv)
142 {
143 int rc;
144
145 frr_preinit (&babeld_di, argc, argv);
146 frr_opt_add ("", longopts, "");
147
148 babel_init_random();
149
150 /* set the Babel's default link-local multicast address and Babel's port */
151 parse_address("ff02:0:0:0:0:0:1:6", protocol_group, NULL);
152 protocol_port = 6696;
153
154 /* get options */
155 while(1) {
156 int opt;
157
158 opt = frr_getopt (argc, argv, NULL);
159
160 if (opt == EOF)
161 break;
162
163 switch (opt)
164 {
165 case 0:
166 break;
167 default:
168 frr_help_exit(1);
169 }
170 }
171
172 snprintf(state_file, sizeof(state_file), "%s/%s",
173 frr_vtydir, "babel-state");
174
175 /* create the threads handler */
176 master = frr_init ();
177
178 /* Library inits. */
179 babel_error_init();
180
181 resend_delay = BABEL_DEFAULT_RESEND_DELAY;
182 change_smoothing_half_life(BABEL_DEFAULT_SMOOTHING_HALF_LIFE);
183
184 /* init some quagga's dependencies, and babeld's commands */
185 if_zapi_callbacks(babel_ifp_create, babel_ifp_up,
186 babel_ifp_down, babel_ifp_destroy);
187 babeld_quagga_init();
188 /* init zebra client's structure and it's commands */
189 /* this replace kernel_setup && kernel_setup_socket */
190 babelz_zebra_init ();
191
192 /* init buffer */
193 rc = resize_receive_buffer(1500);
194 if(rc < 0)
195 babel_fail();
196
197 schedule_neighbours_check(5000, 1);
198
199 frr_config_fork();
200 frr_run(master);
201
202 return 0;
203 }
204
205 static void
206 babel_fail(void)
207 {
208 exit(1);
209 }
210
211 /* initialize random value, and set 'babel_now' by the way. */
212 static void
213 babel_init_random(void)
214 {
215 gettime(&babel_now);
216 int rc;
217 unsigned int seed;
218
219 rc = read_random_bytes(&seed, sizeof(seed));
220 if(rc < 0) {
221 flog_err_sys(EC_LIB_SYSTEM_CALL, "read(random): %s",
222 safe_strerror(errno));
223 seed = 42;
224 }
225
226 seed ^= (babel_now.tv_sec ^ babel_now.tv_usec);
227 srandom(seed);
228 }
229
230 /*
231 Load the state file: check last babeld's running state, usefull in case of
232 "/etc/init.d/babeld restart"
233 */
234 void
235 babel_load_state_file(void)
236 {
237 int fd;
238 int rc;
239
240 fd = open(state_file, O_RDONLY);
241 if(fd < 0 && errno != ENOENT)
242 flog_err_sys(EC_LIB_SYSTEM_CALL, "open(babel-state: %s)",
243 safe_strerror(errno));
244 rc = unlink(state_file);
245 if(fd >= 0 && rc < 0) {
246 flog_err_sys(EC_LIB_SYSTEM_CALL, "unlink(babel-state): %s",
247 safe_strerror(errno));
248 /* If we couldn't unlink it, it's probably stale. */
249 goto fini;
250 }
251 if(fd >= 0) {
252 char buf[100];
253 char buf2[100];
254 int s;
255 long t;
256 rc = read(fd, buf, 99);
257 if(rc < 0) {
258 flog_err_sys(EC_LIB_SYSTEM_CALL, "read(babel-state): %s",
259 safe_strerror(errno));
260 } else {
261 buf[rc] = '\0';
262 rc = sscanf(buf, "%99s %d %ld\n", buf2, &s, &t);
263 if(rc == 3 && s >= 0 && s <= 0xFFFF) {
264 unsigned char sid[8];
265 rc = parse_eui64(buf2, sid);
266 if(rc < 0) {
267 flog_err(EC_BABEL_CONFIG, "Couldn't parse babel-state.");
268 } else {
269 struct timeval realnow;
270 debugf(BABEL_DEBUG_COMMON,
271 "Got %s %d %ld from babel-state.",
272 format_eui64(sid), s, t);
273 gettimeofday(&realnow, NULL);
274 if(memcmp(sid, myid, 8) == 0)
275 myseqno = seqno_plus(s, 1);
276 else
277 flog_err(EC_BABEL_CONFIG,
278 "ID mismatch in babel-state. id=%s; old=%s",
279 format_eui64(myid),
280 format_eui64(sid));
281 }
282 } else {
283 flog_err(EC_BABEL_CONFIG, "Couldn't parse babel-state.");
284 }
285 }
286 goto fini;
287 }
288 fini:
289 if (fd >= 0)
290 close(fd);
291 return ;
292 }
293
294 static void
295 babel_exit_properly(void)
296 {
297 debugf(BABEL_DEBUG_COMMON, "Exiting...");
298 usleep(roughly(10000));
299 gettime(&babel_now);
300
301 /* Uninstall and flush all routes. */
302 debugf(BABEL_DEBUG_COMMON, "Uninstall routes.");
303 flush_all_routes();
304 babel_interface_close_all();
305 babel_zebra_close_connexion();
306 babel_save_state_file();
307 debugf(BABEL_DEBUG_COMMON, "Remove pid file.");
308 debugf(BABEL_DEBUG_COMMON, "Done.");
309 frr_fini();
310
311 exit(0);
312 }
313
314 static void
315 babel_save_state_file(void)
316 {
317 int fd;
318 int rc;
319
320 debugf(BABEL_DEBUG_COMMON, "Save state file.");
321 fd = open(state_file, O_WRONLY | O_TRUNC | O_CREAT, 0644);
322 if(fd < 0) {
323 flog_err_sys(EC_LIB_SYSTEM_CALL, "creat(babel-state): %s",
324 safe_strerror(errno));
325 unlink(state_file);
326 } else {
327 struct timeval realnow;
328 char buf[100];
329 gettimeofday(&realnow, NULL);
330 rc = snprintf(buf, 100, "%s %d %ld\n",
331 format_eui64(myid), (int)myseqno,
332 (long)realnow.tv_sec);
333 if(rc < 0 || rc >= 100) {
334 flog_err(EC_BABEL_CONFIG, "write(babel-state): overflow.");
335 unlink(state_file);
336 } else {
337 rc = write(fd, buf, rc);
338 if(rc < 0) {
339 flog_err(EC_BABEL_CONFIG, "write(babel-state): %s",
340 safe_strerror(errno));
341 unlink(state_file);
342 }
343 fsync(fd);
344 }
345 close(fd);
346 }
347 }
348
349 void
350 show_babel_main_configuration (struct vty *vty)
351 {
352 vty_out (vty,
353 "state file = %s\n"
354 "configuration file = %s\n"
355 "protocol information:\n"
356 " multicast address = %s\n"
357 " port = %d\n"
358 "vty address = %s\n"
359 "vty port = %d\n"
360 "id = %s\n"
361 "kernel_metric = %d\n",
362 state_file,
363 babeld_di.config_file ? babeld_di.config_file : babel_config_default,
364 format_address(protocol_group),
365 protocol_port,
366 babel_vty_addr ? babel_vty_addr : "None",
367 babel_vty_port,
368 format_eui64(myid),
369 kernel_metric);
370 }