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