]> git.proxmox.com Git - mirror_frr.git/blob - babeld/babel_main.c
*: remove VTYNL, part 5 of 6
[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_config_file = NULL;
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 static 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 quagga_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 FRR_DAEMON_INFO(babeld, BABELD,
139 .vty_port = BABEL_VTY_PORT,
140 .proghelp = "Implementation of the BABEL routing protocol.",
141
142 .signals = babel_signals,
143 .n_signals = array_size(babel_signals),
144
145 .privs = &babeld_privs,
146 )
147
148 int
149 main(int argc, char **argv)
150 {
151 int rc;
152
153 frr_preinit (&babeld_di, argc, argv);
154 frr_opt_add ("", longopts, "");
155
156 babel_init_random();
157
158 /* set the Babel's default link-local multicast address and Babel's port */
159 parse_address("ff02:0:0:0:0:0:1:6", protocol_group, NULL);
160 protocol_port = 6696;
161
162 /* get options */
163 while(1) {
164 int opt;
165
166 opt = frr_getopt (argc, argv, NULL);
167
168 if (opt == EOF)
169 break;
170
171 switch (opt)
172 {
173 case 0:
174 break;
175 default:
176 frr_help_exit (1);
177 break;
178 }
179 }
180
181 /* create the threads handler */
182 master = frr_init ();
183
184 /* Library inits. */
185 zprivs_init (&babeld_privs);
186 cmd_init (1);
187 vty_init (master);
188
189 resend_delay = BABEL_DEFAULT_RESEND_DELAY;
190 change_smoothing_half_life(BABEL_DEFAULT_SMOOTHING_HALF_LIFE);
191
192 babel_replace_by_null(STDIN_FILENO);
193
194 /* init some quagga's dependencies, and babeld's commands */
195 babeld_quagga_init();
196 /* init zebra client's structure and it's commands */
197 /* this replace kernel_setup && kernel_setup_socket */
198 babelz_zebra_init ();
199
200 /* Get zebra configuration file. */
201 vty_read_config (babel_config_file, babel_config_default);
202
203 /* init buffer */
204 rc = resize_receive_buffer(1500);
205 if(rc < 0)
206 babel_fail();
207
208 schedule_neighbours_check(5000, 1);
209
210 zlog_notice ("BABELd %s starting: vty@%d", BABEL_VERSION, babel_vty_port);
211
212 frr_config_fork();
213 frr_run(master);
214
215 return 0;
216 }
217
218 static void
219 babel_fail(void)
220 {
221 exit(1);
222 }
223
224 /* initialize random value, and set 'babel_now' by the way. */
225 static void
226 babel_init_random(void)
227 {
228 gettime(&babel_now);
229 int rc;
230 unsigned int seed;
231
232 rc = read_random_bytes(&seed, sizeof(seed));
233 if(rc < 0) {
234 zlog_err("read(random): %s", safe_strerror(errno));
235 seed = 42;
236 }
237
238 seed ^= (babel_now.tv_sec ^ babel_now.tv_usec);
239 srandom(seed);
240 }
241
242 /*
243 close fd, and replace it by "/dev/null"
244 exit if error
245 */
246 static void
247 babel_replace_by_null(int fd)
248 {
249 int fd_null;
250 int rc;
251
252 fd_null = open("/dev/null", O_RDONLY);
253 if(fd_null < 0) {
254 zlog_err("open(null): %s", safe_strerror(errno));
255 exit(1);
256 }
257
258 rc = dup2(fd_null, fd);
259 if(rc < 0) {
260 zlog_err("dup2(null, 0): %s", safe_strerror(errno));
261 exit(1);
262 }
263
264 close(fd_null);
265 }
266
267 /*
268 Load the state file: check last babeld's running state, usefull in case of
269 "/etc/init.d/babeld restart"
270 */
271 void
272 babel_load_state_file(void)
273 {
274 int fd;
275 int rc;
276
277 fd = open(state_file, O_RDONLY);
278 if(fd < 0 && errno != ENOENT)
279 zlog_err("open(babel-state: %s)", safe_strerror(errno));
280 rc = unlink(state_file);
281 if(fd >= 0 && rc < 0) {
282 zlog_err("unlink(babel-state): %s", safe_strerror(errno));
283 /* If we couldn't unlink it, it's probably stale. */
284 close(fd);
285 fd = -1;
286 }
287 if(fd >= 0) {
288 char buf[100];
289 char buf2[100];
290 int s;
291 long t;
292 rc = read(fd, buf, 99);
293 if(rc < 0) {
294 zlog_err("read(babel-state): %s", safe_strerror(errno));
295 } else {
296 buf[rc] = '\0';
297 rc = sscanf(buf, "%99s %d %ld\n", buf2, &s, &t);
298 if(rc == 3 && s >= 0 && s <= 0xFFFF) {
299 unsigned char sid[8];
300 rc = parse_eui64(buf2, sid);
301 if(rc < 0) {
302 zlog_err("Couldn't parse babel-state.");
303 } else {
304 struct timeval realnow;
305 debugf(BABEL_DEBUG_COMMON,
306 "Got %s %d %ld from babel-state.",
307 format_eui64(sid), s, t);
308 gettimeofday(&realnow, NULL);
309 if(memcmp(sid, myid, 8) == 0)
310 myseqno = seqno_plus(s, 1);
311 else
312 zlog_err("ID mismatch in babel-state. id=%s; old=%s",
313 format_eui64(myid),
314 format_eui64(sid));
315 }
316 } else {
317 zlog_err("Couldn't parse babel-state.");
318 }
319 }
320 close(fd);
321 fd = -1;
322 }
323 }
324
325 static void
326 babel_exit_properly(void)
327 {
328 debugf(BABEL_DEBUG_COMMON, "Exiting...");
329 usleep(roughly(10000));
330 gettime(&babel_now);
331
332 /* Uninstall and flush all routes. */
333 debugf(BABEL_DEBUG_COMMON, "Uninstall routes.");
334 flush_all_routes();
335 babel_interface_close_all();
336 babel_zebra_close_connexion();
337 babel_save_state_file();
338 debugf(BABEL_DEBUG_COMMON, "Remove pid file.");
339 debugf(BABEL_DEBUG_COMMON, "Done.");
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 babel_config_file ? babel_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 }