]>
Commit | Line | Data |
---|---|---|
acddc0ed | 1 | // SPDX-License-Identifier: MIT |
ca10883e DS |
2 | /* |
3 | Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek | |
ca10883e DS |
4 | */ |
5 | ||
6 | /* include zebra library */ | |
7 | #include <zebra.h> | |
8 | #include "getopt.h" | |
9 | #include "if.h" | |
10 | #include "log.h" | |
cb37cb33 | 11 | #include "event.h" |
ca10883e DS |
12 | #include "privs.h" |
13 | #include "sigevent.h" | |
09781197 | 14 | #include "lib/version.h" |
ca10883e DS |
15 | #include "command.h" |
16 | #include "vty.h" | |
17 | #include "memory.h" | |
18 | #include "libfrr.h" | |
f135ba52 | 19 | #include "lib_errors.h" |
ca10883e DS |
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" | |
f135ba52 | 32 | #include "babel_errors.h" |
ca10883e | 33 | |
ca10883e DS |
34 | static void babel_fail(void); |
35 | static void babel_init_random(void); | |
ca10883e DS |
36 | static void babel_exit_properly(void); |
37 | static void babel_save_state_file(void); | |
38 | ||
39 | ||
40 | struct thread_master *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 | ||
43e587c1 | 53 | static char state_file[1024]; |
ca10883e DS |
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 | ||
2b64873d | 59 | static const char babel_config_default[] = SYSCONFDIR BABEL_DEFAULT_CONFIG; |
ca10883e DS |
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 | }; | |
900b8c58 | 69 | |
346526cc | 70 | struct zebra_privs_t babeld_privs = |
ca10883e | 71 | { |
dd329373 DS |
72 | #if defined(FRR_USER) |
73 | .user = FRR_USER, | |
ca10883e | 74 | #endif |
dd329373 DS |
75 | #if defined FRR_GROUP |
76 | .group = FRR_GROUP, | |
ca10883e DS |
77 | #endif |
78 | #ifdef VTY_GROUP | |
79 | .vty_group = VTY_GROUP, | |
80 | #endif | |
81 | .caps_p = _caps_p, | |
900b8c58 | 82 | .cap_num_p = array_size(_caps_p), |
ca10883e DS |
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 | ||
7cc91e67 | 100 | static struct frr_signal_t babel_signals[] = |
ca10883e DS |
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 | ||
6fd8972a | 121 | static const struct frr_yang_module_info *const babeld_yang_modules[] = { |
fb7f5aa8 | 122 | &frr_filter_info, |
6fd8972a CS |
123 | &frr_interface_info, |
124 | &frr_vrf_info, | |
125 | }; | |
8fcdd0d6 | 126 | |
ca10883e DS |
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, | |
8fcdd0d6 RW |
135 | |
136 | .yang_modules = babeld_yang_modules, | |
137 | .n_yang_modules = array_size(babeld_yang_modules), | |
80413c20 | 138 | ); |
ca10883e DS |
139 | |
140 | int | |
141 | main(int argc, char **argv) | |
142 | { | |
900b8c58 | 143 | int rc; |
ca10883e | 144 | |
900b8c58 DS |
145 | frr_preinit (&babeld_di, argc, argv); |
146 | frr_opt_add ("", longopts, ""); | |
f135ba52 | 147 | |
ca10883e DS |
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: | |
d10bda27 | 168 | frr_help_exit(1); |
ca10883e DS |
169 | } |
170 | } | |
171 | ||
3c649c71 DS |
172 | snprintf(state_file, sizeof(state_file), "%s/%s", |
173 | frr_vtydir, "babel-state"); | |
174 | ||
ca10883e | 175 | /* create the threads handler */ |
900b8c58 | 176 | master = frr_init (); |
ca10883e DS |
177 | |
178 | /* Library inits. */ | |
f135ba52 | 179 | babel_error_init(); |
ca10883e DS |
180 | |
181 | resend_delay = BABEL_DEFAULT_RESEND_DELAY; | |
182 | change_smoothing_half_life(BABEL_DEFAULT_SMOOTHING_HALF_LIFE); | |
183 | ||
ca10883e | 184 | /* init some quagga's dependencies, and babeld's commands */ |
138c5a74 DS |
185 | if_zapi_callbacks(babel_ifp_create, babel_ifp_up, |
186 | babel_ifp_down, babel_ifp_destroy); | |
ca10883e DS |
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 | ||
ca10883e DS |
192 | /* init buffer */ |
193 | rc = resize_receive_buffer(1500); | |
194 | if(rc < 0) | |
195 | babel_fail(); | |
196 | ||
197 | schedule_neighbours_check(5000, 1); | |
198 | ||
900b8c58 DS |
199 | frr_config_fork(); |
200 | frr_run(master); | |
201 | ||
202 | return 0; | |
ca10883e DS |
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) { | |
450971aa | 221 | flog_err_sys(EC_LIB_SYSTEM_CALL, "read(random): %s", |
f135ba52 | 222 | safe_strerror(errno)); |
ca10883e DS |
223 | seed = 42; |
224 | } | |
225 | ||
226 | seed ^= (babel_now.tv_sec ^ babel_now.tv_usec); | |
227 | srandom(seed); | |
228 | } | |
229 | ||
ca10883e DS |
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) | |
450971aa | 242 | flog_err_sys(EC_LIB_SYSTEM_CALL, "open(babel-state: %s)", |
f135ba52 | 243 | safe_strerror(errno)); |
ca10883e DS |
244 | rc = unlink(state_file); |
245 | if(fd >= 0 && rc < 0) { | |
450971aa | 246 | flog_err_sys(EC_LIB_SYSTEM_CALL, "unlink(babel-state): %s", |
f135ba52 | 247 | safe_strerror(errno)); |
ca10883e | 248 | /* If we couldn't unlink it, it's probably stale. */ |
c31a793b | 249 | goto fini; |
ca10883e DS |
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) { | |
450971aa | 258 | flog_err_sys(EC_LIB_SYSTEM_CALL, "read(babel-state): %s", |
f135ba52 | 259 | safe_strerror(errno)); |
ca10883e DS |
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) { | |
5b003f31 | 267 | flog_err(EC_BABEL_CONFIG, "Couldn't parse babel-state."); |
ca10883e DS |
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 | |
5b003f31 | 277 | flog_err(EC_BABEL_CONFIG, |
e33b116c | 278 | "ID mismatch in babel-state. id=%s; old=%s", |
ca10883e DS |
279 | format_eui64(myid), |
280 | format_eui64(sid)); | |
281 | } | |
282 | } else { | |
5b003f31 | 283 | flog_err(EC_BABEL_CONFIG, "Couldn't parse babel-state."); |
ca10883e DS |
284 | } |
285 | } | |
c31a793b | 286 | goto fini; |
ca10883e | 287 | } |
c31a793b VJ |
288 | fini: |
289 | if (fd >= 0) | |
290 | close(fd); | |
291 | return ; | |
ca10883e DS |
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."); | |
8879bd22 | 309 | frr_fini(); |
ca10883e DS |
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) { | |
450971aa | 323 | flog_err_sys(EC_LIB_SYSTEM_CALL, "creat(babel-state): %s", |
f135ba52 | 324 | safe_strerror(errno)); |
ca10883e DS |
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) { | |
5b003f31 | 334 | flog_err(EC_BABEL_CONFIG, "write(babel-state): overflow."); |
ca10883e DS |
335 | unlink(state_file); |
336 | } else { | |
337 | rc = write(fd, buf, rc); | |
338 | if(rc < 0) { | |
5b003f31 | 339 | flog_err(EC_BABEL_CONFIG, "write(babel-state): %s", |
e33b116c | 340 | safe_strerror(errno)); |
ca10883e DS |
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 | { | |
181039f3 | 352 | vty_out (vty, |
cdda2010 DL |
353 | "state file = %s\n" |
354 | "configuration file = %s\n" | |
0437e105 | 355 | "protocol information:\n" |
cdda2010 DL |
356 | " multicast address = %s\n" |
357 | " port = %d\n" | |
358 | "vty address = %s\n" | |
359 | "vty port = %d\n" | |
360 | "id = %s\n" | |
181039f3 | 361 | "kernel_metric = %d\n", |
cdda2010 | 362 | state_file, |
f714218e | 363 | babeld_di.config_file ? babeld_di.config_file : babel_config_default, |
cdda2010 DL |
364 | format_address(protocol_group), |
365 | protocol_port, | |
ca10883e | 366 | babel_vty_addr ? babel_vty_addr : "None", |
cdda2010 DL |
367 | babel_vty_port, |
368 | format_eui64(myid), | |
96ade3ed | 369 | kernel_metric); |
ca10883e | 370 | } |