File: | src/usr.sbin/eigrpd/eigrpd.c |
Warning: | line 697, column 8 Although the value stored to 'iface' is used in the enclosing expression, the value is never actually read from 'iface' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: eigrpd.c,v 1.29 2023/03/08 04:43:13 guenther Exp $ */ |
2 | |
3 | /* |
4 | * Copyright (c) 2015 Renato Westphal <renato@openbsd.org> |
5 | * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> |
6 | * Copyright (c) 2004 Esben Norby <norby@openbsd.org> |
7 | * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> |
8 | * |
9 | * Permission to use, copy, modify, and distribute this software for any |
10 | * purpose with or without fee is hereby granted, provided that the above |
11 | * copyright notice and this permission notice appear in all copies. |
12 | * |
13 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
14 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
15 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
16 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
17 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
18 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
19 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
20 | */ |
21 | |
22 | #include <sys/types.h> |
23 | #include <sys/wait.h> |
24 | #include <sys/sysctl.h> |
25 | |
26 | #include <err.h> |
27 | #include <errno(*__errno()).h> |
28 | #include <fcntl.h> |
29 | #include <pwd.h> |
30 | #include <signal.h> |
31 | #include <stdio.h> |
32 | #include <stdlib.h> |
33 | #include <string.h> |
34 | #include <unistd.h> |
35 | |
36 | #include "eigrpd.h" |
37 | #include "eigrpe.h" |
38 | #include "rde.h" |
39 | #include "log.h" |
40 | |
41 | static void main_sig_handler(int, short, void *); |
42 | static __dead__attribute__((__noreturn__)) void usage(void); |
43 | static __dead__attribute__((__noreturn__)) void eigrpd_shutdown(void); |
44 | static pid_t start_child(enum eigrpd_process, char *, int, int, int, |
45 | char *); |
46 | static void main_dispatch_eigrpe(int, short, void *); |
47 | static void main_dispatch_rde(int, short, void *); |
48 | static int main_imsg_send_ipc_sockets(struct imsgbuf *, |
49 | struct imsgbuf *); |
50 | static int main_imsg_send_config(struct eigrpd_conf *); |
51 | static int eigrp_reload(void); |
52 | static int eigrp_sendboth(enum imsg_type, void *, uint16_t); |
53 | static void merge_instances(struct eigrpd_conf *, struct eigrp *, |
54 | struct eigrp *); |
55 | |
56 | struct eigrpd_conf *eigrpd_conf; |
57 | |
58 | static char *conffile; |
59 | static struct imsgev *iev_eigrpe; |
60 | static struct imsgev *iev_rde; |
61 | static pid_t eigrpe_pid; |
62 | static pid_t rde_pid; |
63 | |
64 | static void |
65 | main_sig_handler(int sig, short event, void *arg) |
66 | { |
67 | /* signal handler rules don't apply, libevent decouples for us */ |
68 | switch (sig) { |
69 | case SIGTERM15: |
70 | case SIGINT2: |
71 | eigrpd_shutdown(); |
72 | /* NOTREACHED */ |
73 | case SIGHUP1: |
74 | if (eigrp_reload() == -1) |
75 | log_warnx("configuration reload failed"); |
76 | else |
77 | log_debug("configuration reloaded"); |
78 | break; |
79 | default: |
80 | fatalx("unexpected signal"); |
81 | /* NOTREACHED */ |
82 | } |
83 | } |
84 | |
85 | static __dead__attribute__((__noreturn__)) void |
86 | usage(void) |
87 | { |
88 | extern char *__progname; |
89 | |
90 | fprintf(stderr(&__sF[2]), "usage: %s [-dnv] [-D macro=value]" |
91 | " [-f file] [-s socket]\n", |
92 | __progname); |
93 | exit(1); |
94 | } |
95 | |
96 | struct eigrpd_global global; |
97 | |
98 | int |
99 | main(int argc, char *argv[]) |
100 | { |
101 | struct event ev_sigint, ev_sigterm, ev_sighup; |
102 | char *saved_argv0; |
103 | int ch; |
104 | int debug = 0, rflag = 0, eflag = 0; |
105 | int ipforwarding; |
106 | int mib[4]; |
107 | size_t len; |
108 | char *sockname; |
109 | int pipe_parent2eigrpe[2]; |
110 | int pipe_parent2rde[2]; |
111 | |
112 | conffile = CONF_FILE"/etc/eigrpd.conf"; |
113 | log_procname = "parent"; |
114 | sockname = EIGRPD_SOCKET"/var/run/eigrpd.sock"; |
115 | |
116 | log_init(1); /* log to stderr until daemonized */ |
117 | log_verbose(1); |
118 | |
119 | saved_argv0 = argv[0]; |
120 | if (saved_argv0 == NULL((void *)0)) |
121 | saved_argv0 = "eigrpd"; |
122 | |
123 | while ((ch = getopt(argc, argv, "dD:f:ns:vRE")) != -1) { |
124 | switch (ch) { |
125 | case 'd': |
126 | debug = 1; |
127 | break; |
128 | case 'D': |
129 | if (cmdline_symset(optarg) < 0) |
130 | log_warnx("could not parse macro definition %s", |
131 | optarg); |
132 | break; |
133 | case 'f': |
134 | conffile = optarg; |
135 | break; |
136 | case 'n': |
137 | global.cmd_opts |= EIGRPD_OPT_NOACTION0x00000004; |
138 | break; |
139 | case 's': |
140 | sockname = optarg; |
141 | break; |
142 | case 'v': |
143 | if (global.cmd_opts & EIGRPD_OPT_VERBOSE0x00000001) |
144 | global.cmd_opts |= EIGRPD_OPT_VERBOSE20x00000002; |
145 | global.cmd_opts |= EIGRPD_OPT_VERBOSE0x00000001; |
146 | break; |
147 | case 'R': |
148 | rflag = 1; |
149 | break; |
150 | case 'E': |
151 | eflag = 1; |
152 | break; |
153 | default: |
154 | usage(); |
155 | /* NOTREACHED */ |
156 | } |
157 | } |
158 | |
159 | argc -= optind; |
160 | argv += optind; |
161 | if (argc > 0 || (rflag && eflag)) |
162 | usage(); |
163 | |
164 | if (rflag) |
165 | rde(debug, global.cmd_opts & EIGRPD_OPT_VERBOSE0x00000001); |
166 | else if (eflag) |
167 | eigrpe(debug, global.cmd_opts & EIGRPD_OPT_VERBOSE0x00000001, sockname); |
168 | |
169 | mib[0] = CTL_NET4; |
170 | mib[1] = PF_INET2; |
171 | mib[2] = IPPROTO_IP0; |
172 | mib[3] = IPCTL_FORWARDING1; |
173 | len = sizeof(ipforwarding); |
174 | if (sysctl(mib, 4, &ipforwarding, &len, NULL((void *)0), 0) == -1) |
175 | log_warn("sysctl"); |
176 | |
177 | if (ipforwarding != 1) |
178 | log_warnx("WARNING: IP forwarding NOT enabled"); |
179 | |
180 | /* fetch interfaces early */ |
181 | kif_init(); |
182 | |
183 | /* parse config file */ |
184 | if ((eigrpd_conf = parse_config(conffile)) == NULL((void *)0)) { |
185 | kif_clear(); |
186 | exit(1); |
187 | } |
188 | |
189 | if (global.cmd_opts & EIGRPD_OPT_NOACTION0x00000004) { |
190 | if (global.cmd_opts & EIGRPD_OPT_VERBOSE0x00000001) |
191 | print_config(eigrpd_conf); |
192 | else |
193 | fprintf(stderr(&__sF[2]), "configuration OK\n"); |
194 | kif_clear(); |
195 | exit(0); |
196 | } |
197 | |
198 | /* check for root privileges */ |
199 | if (geteuid()) |
200 | errx(1, "need root privileges"); |
201 | |
202 | /* check for eigrpd user */ |
203 | if (getpwnam(EIGRPD_USER"_eigrpd") == NULL((void *)0)) |
204 | errx(1, "unknown user %s", EIGRPD_USER"_eigrpd"); |
205 | |
206 | log_init(debug); |
207 | log_verbose(global.cmd_opts & EIGRPD_OPT_VERBOSE0x00000001); |
208 | |
209 | if (!debug) |
210 | daemon(1, 0); |
211 | |
212 | log_info("startup"); |
213 | |
214 | if (socketpair(AF_UNIX1, SOCK_STREAM1 | SOCK_CLOEXEC0x8000 | SOCK_NONBLOCK0x4000, |
215 | PF_UNSPEC0, pipe_parent2eigrpe) == -1) |
216 | fatal("socketpair"); |
217 | if (socketpair(AF_UNIX1, SOCK_STREAM1 | SOCK_CLOEXEC0x8000 | SOCK_NONBLOCK0x4000, |
218 | PF_UNSPEC0, pipe_parent2rde) == -1) |
219 | fatal("socketpair"); |
220 | |
221 | /* start children */ |
222 | rde_pid = start_child(PROC_RDE_ENGINE, saved_argv0, pipe_parent2rde[1], |
223 | debug, global.cmd_opts & EIGRPD_OPT_VERBOSE0x00000001, NULL((void *)0)); |
224 | eigrpe_pid = start_child(PROC_EIGRP_ENGINE, saved_argv0, |
225 | pipe_parent2eigrpe[1], debug, global.cmd_opts & EIGRPD_OPT_VERBOSE0x00000001, |
226 | sockname); |
227 | |
228 | event_init(); |
229 | |
230 | /* setup signal handler */ |
231 | signal_set(&ev_sigint, SIGINT, main_sig_handler, NULL)event_set(&ev_sigint, 2, 0x08|0x10, main_sig_handler, ((void *)0)); |
232 | signal_set(&ev_sigterm, SIGTERM, main_sig_handler, NULL)event_set(&ev_sigterm, 15, 0x08|0x10, main_sig_handler, ( (void *)0)); |
233 | signal_set(&ev_sighup, SIGHUP, main_sig_handler, NULL)event_set(&ev_sighup, 1, 0x08|0x10, main_sig_handler, ((void *)0)); |
234 | signal_add(&ev_sigint, NULL)event_add(&ev_sigint, ((void *)0)); |
235 | signal_add(&ev_sigterm, NULL)event_add(&ev_sigterm, ((void *)0)); |
236 | signal_add(&ev_sighup, NULL)event_add(&ev_sighup, ((void *)0)); |
237 | signal(SIGPIPE13, SIG_IGN(void (*)(int))1); |
238 | |
239 | /* setup pipes to children */ |
240 | if ((iev_eigrpe = malloc(sizeof(struct imsgev))) == NULL((void *)0) || |
241 | (iev_rde = malloc(sizeof(struct imsgev))) == NULL((void *)0)) |
242 | fatal(NULL((void *)0)); |
243 | imsg_init(&iev_eigrpe->ibuf, pipe_parent2eigrpe[0]); |
244 | iev_eigrpe->handler = main_dispatch_eigrpe; |
245 | imsg_init(&iev_rde->ibuf, pipe_parent2rde[0]); |
246 | iev_rde->handler = main_dispatch_rde; |
247 | |
248 | /* setup event handler */ |
249 | iev_eigrpe->events = EV_READ0x02; |
250 | event_set(&iev_eigrpe->ev, iev_eigrpe->ibuf.fd, iev_eigrpe->events, |
251 | iev_eigrpe->handler, iev_eigrpe); |
252 | event_add(&iev_eigrpe->ev, NULL((void *)0)); |
253 | |
254 | iev_rde->events = EV_READ0x02; |
255 | event_set(&iev_rde->ev, iev_rde->ibuf.fd, iev_rde->events, |
256 | iev_rde->handler, iev_rde); |
257 | event_add(&iev_rde->ev, NULL((void *)0)); |
258 | |
259 | if (main_imsg_send_ipc_sockets(&iev_eigrpe->ibuf, &iev_rde->ibuf)) |
260 | fatal("could not establish imsg links"); |
261 | main_imsg_send_config(eigrpd_conf); |
262 | |
263 | /* notify eigrpe about existing interfaces and addresses */ |
264 | kif_redistribute(); |
265 | |
266 | if (kr_init(!(eigrpd_conf->flags & EIGRPD_FLAG_NO_FIB_UPDATE0x0001), |
267 | eigrpd_conf->rdomain) == -1) |
268 | fatalx("kr_init failed"); |
269 | |
270 | if (pledge("stdio rpath inet sendfd", NULL((void *)0)) == -1) |
271 | fatal("pledge"); |
272 | |
273 | event_dispatch(); |
274 | |
275 | eigrpd_shutdown(); |
276 | /* NOTREACHED */ |
277 | return (0); |
278 | } |
279 | |
280 | static __dead__attribute__((__noreturn__)) void |
281 | eigrpd_shutdown(void) |
282 | { |
283 | pid_t pid; |
284 | int status; |
285 | |
286 | /* close pipes */ |
287 | msgbuf_clear(&iev_eigrpe->ibuf.w); |
288 | close(iev_eigrpe->ibuf.fd); |
289 | msgbuf_clear(&iev_rde->ibuf.w); |
290 | close(iev_rde->ibuf.fd); |
291 | |
292 | kr_shutdown(); |
293 | config_clear(eigrpd_conf, PROC_MAIN); |
294 | |
295 | log_debug("waiting for children to terminate"); |
296 | do { |
297 | pid = wait(&status); |
298 | if (pid == -1) { |
299 | if (errno(*__errno()) != EINTR4 && errno(*__errno()) != ECHILD10) |
300 | fatal("wait"); |
301 | } else if (WIFSIGNALED(status)(((status) & 0177) != 0177 && ((status) & 0177 ) != 0)) |
302 | log_warnx("%s terminated; signal %d", |
303 | (pid == rde_pid) ? "route decision engine" : |
304 | "eigrp engine", WTERMSIG(status)(((status) & 0177))); |
305 | } while (pid != -1 || (pid == -1 && errno(*__errno()) == EINTR4)); |
306 | |
307 | free(iev_eigrpe); |
308 | free(iev_rde); |
309 | |
310 | log_info("terminating"); |
311 | exit(0); |
312 | } |
313 | |
314 | static pid_t |
315 | start_child(enum eigrpd_process p, char *argv0, int fd, int debug, int verbose, |
316 | char *sockname) |
317 | { |
318 | char *argv[7]; |
319 | int argc = 0; |
320 | pid_t pid; |
321 | |
322 | switch (pid = fork()) { |
323 | case -1: |
324 | fatal("cannot fork"); |
325 | case 0: |
326 | break; |
327 | default: |
328 | close(fd); |
329 | return (pid); |
330 | } |
331 | |
332 | if (fd != 3) { |
333 | if (dup2(fd, 3) == -1) |
334 | fatal("cannot setup imsg fd"); |
335 | } else if (fcntl(fd, F_SETFD2, 0) == -1) |
336 | fatal("cannot setup imsg fd"); |
337 | |
338 | argv[argc++] = argv0; |
339 | switch (p) { |
340 | case PROC_MAIN: |
341 | fatalx("Can not start main process"); |
342 | case PROC_RDE_ENGINE: |
343 | argv[argc++] = "-R"; |
344 | break; |
345 | case PROC_EIGRP_ENGINE: |
346 | argv[argc++] = "-E"; |
347 | break; |
348 | } |
349 | if (debug) |
350 | argv[argc++] = "-d"; |
351 | if (verbose) |
352 | argv[argc++] = "-v"; |
353 | if (sockname) { |
354 | argv[argc++] = "-s"; |
355 | argv[argc++] = sockname; |
356 | } |
357 | argv[argc++] = NULL((void *)0); |
358 | |
359 | execvp(argv0, argv); |
360 | fatal("execvp"); |
361 | } |
362 | |
363 | /* imsg handling */ |
364 | static void |
365 | main_dispatch_eigrpe(int fd, short event, void *bula) |
366 | { |
367 | struct imsgev *iev = bula; |
368 | struct imsgbuf *ibuf; |
369 | struct imsg imsg; |
370 | ssize_t n; |
371 | int shut = 0, verbose; |
372 | |
373 | ibuf = &iev->ibuf; |
374 | |
375 | if (event & EV_READ0x02) { |
376 | if ((n = imsg_read(ibuf)) == -1 && errno(*__errno()) != EAGAIN35) |
377 | fatal("imsg_read error"); |
378 | if (n == 0) /* connection closed */ |
379 | shut = 1; |
380 | } |
381 | if (event & EV_WRITE0x04) { |
382 | if ((n = msgbuf_write(&ibuf->w)) == -1 && errno(*__errno()) != EAGAIN35) |
383 | fatal("msgbuf_write"); |
384 | if (n == 0) /* connection closed */ |
385 | shut = 1; |
386 | } |
387 | |
388 | for (;;) { |
389 | if ((n = imsg_get(ibuf, &imsg)) == -1) |
390 | fatal("imsg_get"); |
391 | |
392 | if (n == 0) |
393 | break; |
394 | |
395 | switch (imsg.hdr.type) { |
396 | case IMSG_CTL_RELOAD: |
397 | if (eigrp_reload() == -1) |
398 | log_warnx("configuration reload failed"); |
399 | else |
400 | log_debug("configuration reloaded"); |
401 | break; |
402 | case IMSG_CTL_FIB_COUPLE: |
403 | kr_fib_couple(); |
404 | break; |
405 | case IMSG_CTL_FIB_DECOUPLE: |
406 | kr_fib_decouple(); |
407 | break; |
408 | case IMSG_CTL_KROUTE: |
409 | kr_show_route(&imsg); |
410 | break; |
411 | case IMSG_CTL_IFINFO: |
412 | if (imsg.hdr.len == IMSG_HEADER_SIZEsizeof(struct imsg_hdr)) |
413 | kr_ifinfo(NULL((void *)0), imsg.hdr.pid); |
414 | else if (imsg.hdr.len == IMSG_HEADER_SIZEsizeof(struct imsg_hdr) + IFNAMSIZ16) |
415 | kr_ifinfo(imsg.data, imsg.hdr.pid); |
416 | else |
417 | log_warnx("IFINFO request with wrong len"); |
418 | break; |
419 | case IMSG_CTL_LOG_VERBOSE: |
420 | /* already checked by eigrpe */ |
421 | memcpy(&verbose, imsg.data, sizeof(verbose)); |
422 | log_verbose(verbose); |
423 | break; |
424 | default: |
425 | log_debug("%s: error handling imsg %d", __func__, |
426 | imsg.hdr.type); |
427 | break; |
428 | } |
429 | imsg_free(&imsg); |
430 | } |
431 | if (!shut) |
432 | imsg_event_add(iev); |
433 | else { |
434 | /* this pipe is dead, so remove the event handler */ |
435 | event_del(&iev->ev); |
436 | event_loopexit(NULL((void *)0)); |
437 | } |
438 | } |
439 | |
440 | static void |
441 | main_dispatch_rde(int fd, short event, void *bula) |
442 | { |
443 | struct imsgev *iev = bula; |
444 | struct imsgbuf *ibuf; |
445 | struct imsg imsg; |
446 | ssize_t n; |
447 | int shut = 0; |
448 | |
449 | ibuf = &iev->ibuf; |
450 | |
451 | if (event & EV_READ0x02) { |
452 | if ((n = imsg_read(ibuf)) == -1 && errno(*__errno()) != EAGAIN35) |
453 | fatal("imsg_read error"); |
454 | if (n == 0) /* connection closed */ |
455 | shut = 1; |
456 | } |
457 | if (event & EV_WRITE0x04) { |
458 | if ((n = msgbuf_write(&ibuf->w)) == -1 && errno(*__errno()) != EAGAIN35) |
459 | fatal("msgbuf_write"); |
460 | if (n == 0) /* connection closed */ |
461 | shut = 1; |
462 | } |
463 | |
464 | for (;;) { |
465 | if ((n = imsg_get(ibuf, &imsg)) == -1) |
466 | fatal("imsg_get"); |
467 | |
468 | if (n == 0) |
469 | break; |
470 | |
471 | switch (imsg.hdr.type) { |
472 | case IMSG_KROUTE_CHANGE: |
473 | if (imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr) != |
474 | sizeof(struct kroute)) |
475 | fatalx("invalid size of IMSG_KROUTE_CHANGE"); |
476 | if (kr_change(imsg.data)) |
477 | log_warnx("%s: error changing route", __func__); |
478 | break; |
479 | case IMSG_KROUTE_DELETE: |
480 | if (imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr) != |
481 | sizeof(struct kroute)) |
482 | fatalx("invalid size of IMSG_KROUTE_DELETE"); |
483 | if (kr_delete(imsg.data)) |
484 | log_warnx("%s: error deleting route", __func__); |
485 | break; |
486 | |
487 | default: |
488 | log_debug("%s: error handling imsg %d", __func__, |
489 | imsg.hdr.type); |
490 | break; |
491 | } |
492 | imsg_free(&imsg); |
493 | } |
494 | if (!shut) |
495 | imsg_event_add(iev); |
496 | else { |
497 | /* this pipe is dead, so remove the event handler */ |
498 | event_del(&iev->ev); |
499 | event_loopexit(NULL((void *)0)); |
500 | } |
501 | } |
502 | |
503 | int |
504 | main_imsg_compose_eigrpe(int type, pid_t pid, void *data, uint16_t datalen) |
505 | { |
506 | if (iev_eigrpe == NULL((void *)0)) |
507 | return (-1); |
508 | return (imsg_compose_event(iev_eigrpe, type, 0, pid, -1, data, datalen)); |
509 | } |
510 | |
511 | int |
512 | main_imsg_compose_rde(int type, pid_t pid, void *data, uint16_t datalen) |
513 | { |
514 | if (iev_rde == NULL((void *)0)) |
515 | return (-1); |
516 | return (imsg_compose_event(iev_rde, type, 0, pid, -1, data, datalen)); |
517 | } |
518 | |
519 | void |
520 | imsg_event_add(struct imsgev *iev) |
521 | { |
522 | iev->events = EV_READ0x02; |
523 | if (iev->ibuf.w.queued) |
524 | iev->events |= EV_WRITE0x04; |
525 | |
526 | event_del(&iev->ev); |
527 | event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev); |
528 | event_add(&iev->ev, NULL((void *)0)); |
529 | } |
530 | |
531 | int |
532 | imsg_compose_event(struct imsgev *iev, uint16_t type, uint32_t peerid, |
533 | pid_t pid, int fd, void *data, uint16_t datalen) |
534 | { |
535 | int ret; |
536 | |
537 | if ((ret = imsg_compose(&iev->ibuf, type, peerid, |
538 | pid, fd, data, datalen)) != -1) |
539 | imsg_event_add(iev); |
540 | return (ret); |
541 | } |
542 | |
543 | static int |
544 | main_imsg_send_ipc_sockets(struct imsgbuf *eigrpe_buf, struct imsgbuf *rde_buf) |
545 | { |
546 | int pipe_eigrpe2rde[2]; |
547 | |
548 | if (socketpair(AF_UNIX1, SOCK_STREAM1 | SOCK_CLOEXEC0x8000 | SOCK_NONBLOCK0x4000, |
549 | PF_UNSPEC0, pipe_eigrpe2rde) == -1) |
550 | return (-1); |
551 | |
552 | if (imsg_compose(eigrpe_buf, IMSG_SOCKET_IPC, 0, 0, pipe_eigrpe2rde[0], |
553 | NULL((void *)0), 0) == -1) |
554 | return (-1); |
555 | if (imsg_compose(rde_buf, IMSG_SOCKET_IPC, 0, 0, pipe_eigrpe2rde[1], |
556 | NULL((void *)0), 0) == -1) |
557 | return (-1); |
558 | |
559 | return (0); |
560 | } |
561 | |
562 | struct eigrp * |
563 | eigrp_find(struct eigrpd_conf *xconf, int af, uint16_t as) |
564 | { |
565 | struct eigrp *eigrp; |
566 | |
567 | TAILQ_FOREACH(eigrp, &xconf->instances, entry)for((eigrp) = ((&xconf->instances)->tqh_first); (eigrp ) != ((void *)0); (eigrp) = ((eigrp)->entry.tqe_next)) |
568 | if (eigrp->af == af && eigrp->as == as) |
569 | return (eigrp); |
570 | |
571 | return (NULL((void *)0)); |
572 | } |
573 | |
574 | static int |
575 | main_imsg_send_config(struct eigrpd_conf *xconf) |
576 | { |
577 | struct eigrp *eigrp; |
578 | struct eigrp_iface *ei; |
579 | |
580 | if (eigrp_sendboth(IMSG_RECONF_CONF, xconf, sizeof(*xconf)) == -1) |
581 | return (-1); |
582 | |
583 | TAILQ_FOREACH(eigrp, &xconf->instances, entry)for((eigrp) = ((&xconf->instances)->tqh_first); (eigrp ) != ((void *)0); (eigrp) = ((eigrp)->entry.tqe_next)) { |
584 | if (eigrp_sendboth(IMSG_RECONF_INSTANCE, eigrp, |
585 | sizeof(*eigrp)) == -1) |
586 | return (-1); |
587 | |
588 | TAILQ_FOREACH(ei, &eigrp->ei_list, e_entry)for((ei) = ((&eigrp->ei_list)->tqh_first); (ei) != ( (void *)0); (ei) = ((ei)->e_entry.tqe_next)) { |
589 | if (eigrp_sendboth(IMSG_RECONF_IFACE, ei->iface, |
590 | sizeof(struct iface)) == -1) |
591 | return (-1); |
592 | |
593 | if (eigrp_sendboth(IMSG_RECONF_EIGRP_IFACE, ei, |
594 | sizeof(*ei)) == -1) |
595 | return (-1); |
596 | } |
597 | } |
598 | |
599 | if (eigrp_sendboth(IMSG_RECONF_END, NULL((void *)0), 0) == -1) |
600 | return (-1); |
601 | |
602 | return (0); |
603 | } |
604 | |
605 | static int |
606 | eigrp_reload(void) |
607 | { |
608 | struct eigrpd_conf *xconf; |
609 | |
610 | if ((xconf = parse_config(conffile)) == NULL((void *)0)) |
611 | return (-1); |
612 | |
613 | if (main_imsg_send_config(xconf) == -1) |
614 | return (-1); |
615 | |
616 | merge_config(eigrpd_conf, xconf, PROC_MAIN); |
617 | |
618 | return (0); |
619 | } |
620 | |
621 | static int |
622 | eigrp_sendboth(enum imsg_type type, void *buf, uint16_t len) |
623 | { |
624 | if (main_imsg_compose_eigrpe(type, 0, buf, len) == -1) |
625 | return (-1); |
626 | if (main_imsg_compose_rde(type, 0, buf, len) == -1) |
627 | return (-1); |
628 | return (0); |
629 | } |
630 | |
631 | void |
632 | merge_config(struct eigrpd_conf *conf, struct eigrpd_conf *xconf, |
633 | enum eigrpd_process proc) |
634 | { |
635 | struct iface *iface, *itmp, *xi; |
636 | struct eigrp *eigrp, *etmp, *xe; |
637 | |
638 | conf->rtr_id = xconf->rtr_id; |
639 | conf->flags = xconf->flags; |
640 | conf->rdomain= xconf->rdomain; |
641 | conf->fib_priority_internal = xconf->fib_priority_internal; |
642 | conf->fib_priority_external = xconf->fib_priority_external; |
643 | conf->fib_priority_summary = xconf->fib_priority_summary; |
644 | |
645 | /* merge instances */ |
646 | TAILQ_FOREACH_SAFE(eigrp, &conf->instances, entry, etmp)for ((eigrp) = ((&conf->instances)->tqh_first); (eigrp ) != ((void *)0) && ((etmp) = ((eigrp)->entry.tqe_next ), 1); (eigrp) = (etmp)) { |
647 | /* find deleted instances */ |
648 | if ((xe = eigrp_find(xconf, eigrp->af, eigrp->as)) == NULL((void *)0)) { |
649 | TAILQ_REMOVE(&conf->instances, eigrp, entry)do { if (((eigrp)->entry.tqe_next) != ((void *)0)) (eigrp) ->entry.tqe_next->entry.tqe_prev = (eigrp)->entry.tqe_prev ; else (&conf->instances)->tqh_last = (eigrp)->entry .tqe_prev; *(eigrp)->entry.tqe_prev = (eigrp)->entry.tqe_next ; ; ; } while (0); |
650 | |
651 | switch (proc) { |
652 | case PROC_RDE_ENGINE: |
653 | rde_instance_del(eigrp); |
654 | break; |
655 | case PROC_EIGRP_ENGINE: |
656 | eigrpe_instance_del(eigrp); |
657 | break; |
658 | case PROC_MAIN: |
659 | free(eigrp); |
660 | break; |
661 | } |
662 | } |
663 | } |
664 | TAILQ_FOREACH_SAFE(xe, &xconf->instances, entry, etmp)for ((xe) = ((&xconf->instances)->tqh_first); (xe) != ((void *)0) && ((etmp) = ((xe)->entry.tqe_next), 1 ); (xe) = (etmp)) { |
665 | /* find new instances */ |
666 | if ((eigrp = eigrp_find(conf, xe->af, xe->as)) == NULL((void *)0)) { |
667 | TAILQ_REMOVE(&xconf->instances, xe, entry)do { if (((xe)->entry.tqe_next) != ((void *)0)) (xe)->entry .tqe_next->entry.tqe_prev = (xe)->entry.tqe_prev; else ( &xconf->instances)->tqh_last = (xe)->entry.tqe_prev ; *(xe)->entry.tqe_prev = (xe)->entry.tqe_next; ; ; } while (0); |
668 | TAILQ_INSERT_TAIL(&conf->instances, xe, entry)do { (xe)->entry.tqe_next = ((void *)0); (xe)->entry.tqe_prev = (&conf->instances)->tqh_last; *(&conf->instances )->tqh_last = (xe); (&conf->instances)->tqh_last = &(xe)->entry.tqe_next; } while (0); |
669 | |
670 | switch (proc) { |
671 | case PROC_RDE_ENGINE: |
672 | rde_instance_init(xe); |
673 | break; |
674 | case PROC_EIGRP_ENGINE: |
675 | eigrpe_instance_init(xe); |
676 | break; |
677 | case PROC_MAIN: |
678 | break; |
679 | } |
680 | continue; |
681 | } |
682 | |
683 | /* update existing instances */ |
684 | merge_instances(conf, eigrp, xe); |
685 | } |
686 | |
687 | /* merge interfaces */ |
688 | TAILQ_FOREACH_SAFE(iface, &conf->iface_list, entry, itmp)for ((iface) = ((&conf->iface_list)->tqh_first); (iface ) != ((void *)0) && ((itmp) = ((iface)->entry.tqe_next ), 1); (iface) = (itmp)) { |
689 | /* find deleted ifaces */ |
690 | if ((xi = if_lookup(xconf, iface->ifindex)) == NULL((void *)0)) { |
691 | TAILQ_REMOVE(&conf->iface_list, iface, entry)do { if (((iface)->entry.tqe_next) != ((void *)0)) (iface) ->entry.tqe_next->entry.tqe_prev = (iface)->entry.tqe_prev ; else (&conf->iface_list)->tqh_last = (iface)-> entry.tqe_prev; *(iface)->entry.tqe_prev = (iface)->entry .tqe_next; ; ; } while (0); |
692 | free(iface); |
693 | } |
694 | } |
695 | TAILQ_FOREACH_SAFE(xi, &xconf->iface_list, entry, itmp)for ((xi) = ((&xconf->iface_list)->tqh_first); (xi) != ((void *)0) && ((itmp) = ((xi)->entry.tqe_next ), 1); (xi) = (itmp)) { |
696 | /* find new ifaces */ |
697 | if ((iface = if_lookup(conf, xi->ifindex)) == NULL((void *)0)) { |
Although the value stored to 'iface' is used in the enclosing expression, the value is never actually read from 'iface' | |
698 | TAILQ_REMOVE(&xconf->iface_list, xi, entry)do { if (((xi)->entry.tqe_next) != ((void *)0)) (xi)->entry .tqe_next->entry.tqe_prev = (xi)->entry.tqe_prev; else ( &xconf->iface_list)->tqh_last = (xi)->entry.tqe_prev ; *(xi)->entry.tqe_prev = (xi)->entry.tqe_next; ; ; } while (0); |
699 | TAILQ_INSERT_TAIL(&conf->iface_list, xi, entry)do { (xi)->entry.tqe_next = ((void *)0); (xi)->entry.tqe_prev = (&conf->iface_list)->tqh_last; *(&conf->iface_list )->tqh_last = (xi); (&conf->iface_list)->tqh_last = &(xi)->entry.tqe_next; } while (0); |
700 | continue; |
701 | } |
702 | |
703 | /* TODO update existing ifaces */ |
704 | } |
705 | |
706 | /* resend addresses to activate new interfaces */ |
707 | if (proc == PROC_MAIN) |
708 | kif_redistribute(); |
709 | |
710 | free(xconf); |
711 | } |
712 | |
713 | static void |
714 | merge_instances(struct eigrpd_conf *xconf, struct eigrp *eigrp, struct eigrp *xe) |
715 | { |
716 | /* TODO */ |
717 | } |
718 | |
719 | struct eigrpd_conf * |
720 | config_new_empty(void) |
721 | { |
722 | struct eigrpd_conf *xconf; |
723 | |
724 | xconf = calloc(1, sizeof(*xconf)); |
725 | if (xconf == NULL((void *)0)) |
726 | fatal(NULL((void *)0)); |
727 | |
728 | TAILQ_INIT(&xconf->instances)do { (&xconf->instances)->tqh_first = ((void *)0); ( &xconf->instances)->tqh_last = &(&xconf-> instances)->tqh_first; } while (0); |
729 | TAILQ_INIT(&xconf->iface_list)do { (&xconf->iface_list)->tqh_first = ((void *)0); (&xconf->iface_list)->tqh_last = &(&xconf-> iface_list)->tqh_first; } while (0); |
730 | |
731 | return (xconf); |
732 | } |
733 | |
734 | void |
735 | config_clear(struct eigrpd_conf *conf, enum eigrpd_process proc) |
736 | { |
737 | struct eigrpd_conf *xconf; |
738 | |
739 | /* merge current config with an empty config */ |
740 | xconf = config_new_empty(); |
741 | merge_config(conf, xconf, proc); |
742 | |
743 | free(conf); |
744 | } |