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