Bug Summary

File:src/usr.sbin/eigrpd/eigrpd.c
Warning:line 161, column 2
Value stored to 'argv' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name eigrpd.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/usr.sbin/eigrpd/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/eigrpd -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/eigrpd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/usr.sbin/eigrpd/eigrpd.c
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
41static void main_sig_handler(int, short, void *);
42static __dead__attribute__((__noreturn__)) void usage(void);
43static __dead__attribute__((__noreturn__)) void eigrpd_shutdown(void);
44static pid_t start_child(enum eigrpd_process, char *, int, int, int,
45 char *);
46static void main_dispatch_eigrpe(int, short, void *);
47static void main_dispatch_rde(int, short, void *);
48static int main_imsg_send_ipc_sockets(struct imsgbuf *,
49 struct imsgbuf *);
50static int main_imsg_send_config(struct eigrpd_conf *);
51static int eigrp_reload(void);
52static int eigrp_sendboth(enum imsg_type, void *, uint16_t);
53static void merge_instances(struct eigrpd_conf *, struct eigrp *,
54 struct eigrp *);
55
56struct eigrpd_conf *eigrpd_conf;
57
58static char *conffile;
59static struct imsgev *iev_eigrpe;
60static struct imsgev *iev_rde;
61static pid_t eigrpe_pid;
62static pid_t rde_pid;
63
64/* ARGSUSED */
65static void
66main_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
86static __dead__attribute__((__noreturn__)) void
87usage(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
97struct eigrpd_global global;
98
99int
100main(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;
Value stored to 'argv' is never read
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
281static __dead__attribute__((__noreturn__)) void
282eigrpd_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
315static pid_t
316start_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 */
366static void
367main_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 */
443static void
444main_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
506int
507main_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
514int
515main_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
522void
523imsg_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
534int
535imsg_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
546static int
547main_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
565struct eigrp *
566eigrp_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
577static int
578main_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
608static int
609eigrp_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
624static int
625eigrp_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
634void
635merge_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)) {
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
716static void
717merge_instances(struct eigrpd_conf *xconf, struct eigrp *eigrp, struct eigrp *xe)
718{
719 /* TODO */
720}
721
722struct eigrpd_conf *
723config_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
737void
738config_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}