Bug Summary

File:src/usr.sbin/ripd/ripe.c
Warning:line 443, column 7
Potential leak of memory pointed to by 'rr'

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 ripe.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/ripd/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/usr.sbin/ripd -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/ripd/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/ripd/ripe.c
1/* $OpenBSD: ripe.c,v 1.30 2021/01/19 10:20:47 claudio Exp $ */
2
3/*
4 * Copyright (c) 2006 Michele Marchetto <mydecay@openbeer.it>
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/socket.h>
24#include <sys/queue.h>
25#include <netinet/in.h>
26#include <arpa/inet.h>
27#include <net/if_types.h>
28#include <stdlib.h>
29#include <signal.h>
30#include <string.h>
31#include <fcntl.h>
32#include <pwd.h>
33#include <unistd.h>
34#include <event.h>
35#include <err.h>
36#include <errno(*__errno()).h>
37#include <stdio.h>
38
39#include "ripd.h"
40#include "rip.h"
41#include "ripe.h"
42#include "log.h"
43#include "control.h"
44
45void ripe_sig_handler(int, short, void *);
46__dead__attribute__((__noreturn__)) void ripe_shutdown(void);
47
48struct ripd_conf *oeconf = NULL((void *)0);
49static struct imsgev *iev_main;
50static struct imsgev *iev_rde;
51
52/* ARGSUSED */
53void
54ripe_sig_handler(int sig, short event, void *bula)
55{
56 switch (sig) {
57 case SIGINT2:
58 case SIGTERM15:
59 ripe_shutdown();
60 /* NOTREACHED */
61 default:
62 fatalx("unexpected signal");
63 }
64}
65
66/* rip engine */
67pid_t
68ripe(struct ripd_conf *xconf, int pipe_parent2ripe[2], int pipe_ripe2rde[2],
69 int pipe_parent2rde[2])
70{
71 struct event ev_sigint, ev_sigterm;
72 struct sockaddr_in addr;
73 struct iface *iface = NULL((void *)0);
74 struct passwd *pw;
75 struct redistribute *r;
76 pid_t pid;
77
78 switch (pid = fork()) {
79 case -1:
80 fatal("cannot fork");
81 case 0:
82 break;
83 default:
84 return (pid);
85 }
86
87 /* create ripd control socket outside chroot */
88 if (control_init(xconf->csock) == -1)
89 fatalx("control socket setup failed");
90
91 addr.sin_family = AF_INET2;
92 addr.sin_port = htons(RIP_PORT)(__uint16_t)(__builtin_constant_p(520) ? (__uint16_t)(((__uint16_t
)(520) & 0xffU) << 8 | ((__uint16_t)(520) & 0xff00U
) >> 8) : __swap16md(520))
;
93 addr.sin_addr.s_addr = INADDR_ANY((u_int32_t)(0x00000000));
94
95 if ((xconf->rip_socket = socket(AF_INET2,
96 SOCK_DGRAM2 | SOCK_CLOEXEC0x8000 | SOCK_NONBLOCK0x4000,
97 IPPROTO_UDP17)) == -1)
98 fatalx("error creating socket");
99
100 if (bind(xconf->rip_socket, (struct sockaddr *)&addr,
101 sizeof(addr)) == -1)
102 fatal("error binding socket");
103
104 /* set some defaults */
105 if (if_set_opt(xconf->rip_socket) == -1)
106 fatal("if_set_opt");
107
108 if (if_set_mcast_ttl(xconf->rip_socket, IP_DEFAULT_MULTICAST_TTL1) == -1)
109 fatal("if_set_mcast_ttl");
110
111 if (if_set_mcast_loop(xconf->rip_socket) == -1)
112 fatal("if_set_mcast_loop");
113
114 if (if_set_tos(xconf->rip_socket, IPTOS_PREC_INTERNETCONTROL0xc0) == -1)
115 fatal("if_set_tos");
116
117 if_set_recvbuf(xconf->rip_socket);
118
119 oeconf = xconf;
120
121 if ((pw = getpwnam(RIPD_USER"_ripd")) == NULL((void *)0))
122 fatal("getpwnam");
123
124 if (chroot(pw->pw_dir) == -1)
125 fatal("chroot");
126 if (chdir("/") == -1)
127 fatal("chdir(\"/\")");
128
129 setproctitle("rip engine");
130 log_procname = "ripe";
131
132 if (setgroups(1, &pw->pw_gid) ||
133 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
134 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
135 fatal("can't drop privileges");
136
137 event_init();
138 nbr_init(NBR_HASHSIZE128);
139
140 /* setup signal handler */
141 signal_set(&ev_sigint, SIGINT, ripe_sig_handler, NULL)event_set(&ev_sigint, 2, 0x08|0x10, ripe_sig_handler, ((void
*)0))
;
142 signal_set(&ev_sigterm, SIGTERM, ripe_sig_handler, NULL)event_set(&ev_sigterm, 15, 0x08|0x10, ripe_sig_handler, (
(void *)0))
;
143 signal_add(&ev_sigint, NULL)event_add(&ev_sigint, ((void *)0));
144 signal_add(&ev_sigterm, NULL)event_add(&ev_sigterm, ((void *)0));
145 signal(SIGPIPE13, SIG_IGN(void (*)(int))1);
146 signal(SIGHUP1, SIG_IGN(void (*)(int))1);
147
148 /* setup pipes */
149 close(pipe_parent2ripe[0]);
150 close(pipe_ripe2rde[1]);
151 close(pipe_parent2rde[0]);
152 close(pipe_parent2rde[1]);
153
154 if ((iev_rde = malloc(sizeof(struct imsgev))) == NULL((void *)0) ||
155 (iev_main = malloc(sizeof(struct imsgev))) == NULL((void *)0))
156 fatal(NULL((void *)0));
157 imsg_init(&iev_rde->ibuf, pipe_ripe2rde[0]);
158 iev_rde->handler = ripe_dispatch_rde;
159 imsg_init(&iev_main->ibuf, pipe_parent2ripe[1]);
160 iev_main->handler = ripe_dispatch_main;
161
162 /* setup event handler */
163 iev_rde->events = EV_READ0x02;
164 event_set(&iev_rde->ev, iev_rde->ibuf.fd, iev_rde->events,
165 iev_rde->handler, iev_rde);
166 event_add(&iev_rde->ev, NULL((void *)0));
167
168 iev_main->events = EV_READ0x02;
169 event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events,
170 iev_main->handler, iev_main);
171 event_add(&iev_main->ev, NULL((void *)0));
172
173 event_set(&oeconf->ev, oeconf->rip_socket, EV_READ0x02|EV_PERSIST0x10,
174 recv_packet, oeconf);
175 event_add(&oeconf->ev, NULL((void *)0));
176
177 /* remove unneeded config stuff */
178 while ((r = SIMPLEQ_FIRST(&oeconf->redist_list)((&oeconf->redist_list)->sqh_first)) != NULL((void *)0)) {
179 SIMPLEQ_REMOVE_HEAD(&oeconf->redist_list, entry)do { if (((&oeconf->redist_list)->sqh_first = (&
oeconf->redist_list)->sqh_first->entry.sqe_next) == (
(void *)0)) (&oeconf->redist_list)->sqh_last = &
(&oeconf->redist_list)->sqh_first; } while (0)
;
180 free(r);
181 }
182
183 /* listen on ripd control socket */
184 control_listen();
185
186 /* start interfaces */
187 LIST_FOREACH(iface, &xconf->iface_list, entry)for((iface) = ((&xconf->iface_list)->lh_first); (iface
)!= ((void *)0); (iface) = ((iface)->entry.le_next))
{
188 if_init(xconf, iface);
189 if (if_fsm(iface, IF_EVT_UP))
190 log_debug("ripe: error starting interface: %s",
191 iface->name);
192 }
193
194 if (pledge("stdio inet mcast", NULL((void *)0)) == -1)
195 fatal("pledge");
196
197 evtimer_set(&oeconf->report_timer, report_timer, oeconf)event_set(&oeconf->report_timer, -1, 0, report_timer, oeconf
)
;
198 start_report_timer();
199
200 ripe_imsg_compose_rde(IMSG_FULL_REQUEST, 0, 0, NULL((void *)0), 0);
201
202 event_dispatch();
203
204 ripe_shutdown();
205 /* NOTREACHED */
206 return (0);
207}
208
209int
210ripe_imsg_compose_parent(int type, pid_t pid, void *data, u_int16_t datalen)
211{
212 return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen));
213}
214
215int
216ripe_imsg_compose_rde(int type, u_int32_t peerid, pid_t pid,
217 void *data, u_int16_t datalen)
218{
219 return (imsg_compose_event(iev_rde, type, peerid, pid, -1,
220 data, datalen));
221}
222
223/* ARGSUSED */
224void
225ripe_dispatch_main(int fd, short event, void *bula)
226{
227 struct imsg imsg;
228 struct imsgev *iev = bula;
229 struct imsgbuf *ibuf = &iev->ibuf;
230 struct kif *kif;
231 struct iface *iface;
232 ssize_t n;
233 int link_ok, shut = 0;
234
235 if (event & EV_READ0x02) {
236 if ((n = imsg_read(ibuf)) == -1 && errno(*__errno()) != EAGAIN35)
237 fatal("imsg_read error");
238 if (n == 0) /* connection closed */
239 shut = 1;
240 }
241 if (event & EV_WRITE0x04) {
242 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno(*__errno()) != EAGAIN35)
243 fatal("msgbuf_write");
244 if (n == 0) /* connection closed */
245 shut = 1;
246 }
247
248 for (;;) {
249 if ((n = imsg_get(ibuf, &imsg)) == -1)
250 fatal("ripe_dispatch_main: imsg_get error");
251 if (n == 0)
252 break;
253
254 switch (imsg.hdr.type) {
255 case IMSG_IFINFO:
256 if (imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr) !=
257 sizeof(struct kif))
258 fatalx("IFINFO imsg with wrong len");
259 kif = imsg.data;
260 link_ok = (kif->flags & IFF_UP0x1) &&
261 LINK_STATE_IS_UP(kif->link_state)((kif->link_state) >= 4 || (kif->link_state) == 0);
262
263 LIST_FOREACH(iface, &oeconf->iface_list, entry)for((iface) = ((&oeconf->iface_list)->lh_first); (iface
)!= ((void *)0); (iface) = ((iface)->entry.le_next))
{
264 if (kif->ifindex == iface->ifindex) {
265 iface->flags = kif->flags;
266 iface->linkstate = kif->link_state;
267
268 if (link_ok) {
269 if_fsm(iface, IF_EVT_UP);
270 log_warnx("interface %s up",
271 iface->name);
272 } else {
273 if_fsm(iface, IF_EVT_DOWN);
274 log_warnx("interface %s down",
275 iface->name);
276 }
277 }
278 }
279 break;
280 case IMSG_CTL_IFINFO:
281 case IMSG_CTL_KROUTE:
282 case IMSG_CTL_KROUTE_ADDR:
283 case IMSG_CTL_END:
284 control_imsg_relay(&imsg);
285 break;
286 default:
287 log_debug("ripe_dispatch_main: error handling imsg %d",
288 imsg.hdr.type);
289 break;
290 }
291 imsg_free(&imsg);
292 }
293 if (!shut)
294 imsg_event_add(iev);
295 else {
296 /* this pipe is dead, so remove the event handler */
297 event_del(&iev->ev);
298 event_loopexit(NULL((void *)0));
299 }
300}
301
302/* ARGSUSED */
303void
304ripe_dispatch_rde(int fd, short event, void *bula)
305{
306 struct rip_route *rr;
307 struct imsg imsg;
308 struct imsgev *iev = bula;
309 struct imsgbuf *ibuf = &iev->ibuf;
310 struct iface *iface;
311 struct nbr *nbr;
312 ssize_t n;
313 int shut = 0;
314
315 if (event & EV_READ0x02) {
1
Assuming the condition is false
2
Taking false branch
316 if ((n = imsg_read(ibuf)) == -1 && errno(*__errno()) != EAGAIN35)
317 fatal("imsg_read error");
318 if (n == 0) /* connection closed */
319 shut = 1;
320 }
321 if (event & EV_WRITE0x04) {
3
Assuming the condition is false
4
Taking false branch
322 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno(*__errno()) != EAGAIN35)
323 fatal("msgbuf_write");
324 if (n == 0) /* connection closed */
325 shut = 1;
326 }
327
328 for (;;) {
5
Loop condition is true. Entering loop body
21
Loop condition is true. Entering loop body
329 if ((n = imsg_get(ibuf, &imsg)) == -1)
6
Assuming the condition is false
7
Taking false branch
22
Assuming the condition is false
23
Taking false branch
330 fatal("ripe_dispatch_rde: imsg_get error");
331 if (n == 0)
8
Assuming 'n' is not equal to 0
9
Taking false branch
24
Assuming 'n' is equal to 0
25
Taking true branch
332 break;
26
Execution continues on line 443
333
334 switch (imsg.hdr.type) {
10
Control jumps to 'case IMSG_RESPONSE_ADD:' at line 376
335 case IMSG_REQUEST_ADD:
336 if (imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr) != sizeof(*rr))
337 fatalx("invalid size of RDE request");
338
339 if ((rr = malloc(sizeof(*rr))) == NULL((void *)0))
340 fatal("ripe_dispatch_rde");
341
342 memcpy(rr, imsg.data, sizeof(*rr));
343
344 if (imsg.hdr.peerid != 0) {
345 if ((nbr = nbr_find_peerid(imsg.hdr.peerid)) ==
346 NULL((void *)0)) {
347 log_debug("unknown neighbor id %u",
348 imsg.hdr.peerid);
349 free(rr);
350 break;
351 }
352 add_entry(&nbr->rq_list, rr);
353 break;
354 }
355
356 LIST_FOREACH(iface, &oeconf->iface_list, entry)for((iface) = ((&oeconf->iface_list)->lh_first); (iface
)!= ((void *)0); (iface) = ((iface)->entry.le_next))
{
357 add_entry(&iface->rq_list, rr);
358 }
359 break;
360 case IMSG_SEND_REQUEST:
361 if (imsg.hdr.peerid != 0) {
362 if ((nbr = nbr_find_peerid(imsg.hdr.peerid)) ==
363 NULL((void *)0)) {
364 log_debug("unknown neighbor id %u",
365 imsg.hdr.peerid);
366 break;
367 }
368 send_request(&nbr->rq_list, NULL((void *)0), nbr);
369 break;
370 }
371
372 LIST_FOREACH(iface, &oeconf->iface_list, entry)for((iface) = ((&oeconf->iface_list)->lh_first); (iface
)!= ((void *)0); (iface) = ((iface)->entry.le_next))
{
373 send_request(&iface->rq_list, iface, NULL((void *)0));
374 }
375 break;
376 case IMSG_RESPONSE_ADD:
377 if (imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr) != sizeof(*rr))
11
Assuming the condition is false
12
Taking false branch
378 fatalx("invalid size of RDE request");
379
380 if ((rr = malloc(sizeof(*rr))) == NULL((void *)0))
13
Memory is allocated
14
Assuming the condition is false
15
Taking false branch
381 fatal("ripe_dispatch_rde");
382
383 memcpy(rr, imsg.data, sizeof(*rr));
384
385 if (imsg.hdr.peerid == 0) {
16
Assuming field 'peerid' is equal to 0
17
Taking true branch
386 LIST_FOREACH(iface, &oeconf->iface_list, entry)for((iface) = ((&oeconf->iface_list)->lh_first); (iface
)!= ((void *)0); (iface) = ((iface)->entry.le_next))
18
Assuming 'iface' is equal to null
19
Loop condition is false. Execution continues on line 389
387 add_entry(&iface->rp_list, rr);
388
389 break;
20
Execution continues on line 441
390 }
391
392 if ((nbr = nbr_find_peerid(imsg.hdr.peerid)) == NULL((void *)0)) {
393 log_debug("unknown neighbor id %u",
394 imsg.hdr.peerid);
395 free(rr);
396 break;
397 }
398 add_entry(&nbr->rp_list, rr);
399
400 break;
401 case IMSG_SEND_RESPONSE:
402 if (imsg.hdr.peerid == 0) {
403 LIST_FOREACH(iface, &oeconf->iface_list,for((iface) = ((&oeconf->iface_list)->lh_first); (iface
)!= ((void *)0); (iface) = ((iface)->entry.le_next))
404 entry)for((iface) = ((&oeconf->iface_list)->lh_first); (iface
)!= ((void *)0); (iface) = ((iface)->entry.le_next))
{
405 send_response(&iface->rp_list,
406 iface, NULL((void *)0));
407 }
408 break;
409 }
410
411 if ((nbr = nbr_find_peerid(imsg.hdr.peerid)) == NULL((void *)0)) {
412 log_debug("unknown neighbor id %u",
413 imsg.hdr.peerid);
414 break;
415 }
416 send_response(&nbr->rp_list, NULL((void *)0), nbr);
417 nbr_fsm(nbr, NBR_EVT_RESPONSE_SENT);
418 break;
419 case IMSG_SEND_TRIGGERED_UPDATE:
420 if (imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr) != sizeof(struct
421 rip_route))
422 fatalx("invalid size of RDE request");
423
424 rr = imsg.data;
425
426 LIST_FOREACH(iface, &oeconf->iface_list,for((iface) = ((&oeconf->iface_list)->lh_first); (iface
)!= ((void *)0); (iface) = ((iface)->entry.le_next))
427 entry)for((iface) = ((&oeconf->iface_list)->lh_first); (iface
)!= ((void *)0); (iface) = ((iface)->entry.le_next))
{
428 if (rr->ifindex != iface->ifindex)
429 send_triggered_update(iface, rr);
430 }
431 break;
432 case IMSG_CTL_END:
433 case IMSG_CTL_SHOW_RIB:
434 control_imsg_relay(&imsg);
435 break;
436 default:
437 log_debug("ripe_dispatch_rde: error handling imsg %d",
438 imsg.hdr.type);
439 break;
440 }
441 imsg_free(&imsg);
442 }
443 if (!shut)
27
Potential leak of memory pointed to by 'rr'
444 imsg_event_add(iev);
445 else {
446 /* this pipe is dead, so remove the event handler */
447 event_del(&iev->ev);
448 event_loopexit(NULL((void *)0));
449 }
450}
451
452__dead__attribute__((__noreturn__)) void
453ripe_shutdown(void)
454{
455 struct iface *iface;
456
457 /* close pipes */
458 msgbuf_write(&iev_rde->ibuf.w);
459 msgbuf_clear(&iev_rde->ibuf.w);
460 close(iev_rde->ibuf.fd);
461 msgbuf_write(&iev_main->ibuf.w);
462 msgbuf_clear(&iev_main->ibuf.w);
463 close(iev_main->ibuf.fd);
464
465 LIST_FOREACH(iface, &oeconf->iface_list, entry)for((iface) = ((&oeconf->iface_list)->lh_first); (iface
)!= ((void *)0); (iface) = ((iface)->entry.le_next))
{
466 if (if_fsm(iface, IF_EVT_DOWN)) {
467 log_debug("error stopping interface %s",
468 iface->name);
469 }
470 }
471 while ((iface = LIST_FIRST(&oeconf->iface_list)((&oeconf->iface_list)->lh_first)) != NULL((void *)0)) {
472 LIST_REMOVE(iface, entry)do { if ((iface)->entry.le_next != ((void *)0)) (iface)->
entry.le_next->entry.le_prev = (iface)->entry.le_prev; *
(iface)->entry.le_prev = (iface)->entry.le_next; ; ; } while
(0)
;
473
474 /* revert the demotion when the interface is deleted */
475 if (iface->state == IF_STA_DOWN0x01)
476 ripe_demote_iface(iface, 1);
477
478 if_del(iface);
479 }
480
481 close(oeconf->rip_socket);
482
483 /* clean up */
484 free(iev_rde);
485 free(iev_main);
486 free(oeconf);
487
488 log_info("rip engine exiting");
489 _exit(0);
490}
491
492void
493ripe_iface_ctl(struct ctl_conn *c, unsigned int idx)
494{
495 struct iface *iface;
496 struct ctl_iface *ictl;
497
498 LIST_FOREACH(iface, &oeconf->iface_list, entry)for((iface) = ((&oeconf->iface_list)->lh_first); (iface
)!= ((void *)0); (iface) = ((iface)->entry.le_next))
{
499 if (idx == 0 || idx == iface->ifindex) {
500 ictl = if_to_ctl(iface);
501 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_IFACE,
502 0, 0, -1, ictl, sizeof(struct ctl_iface));
503 }
504 }
505}
506
507void
508ripe_nbr_ctl(struct ctl_conn *c)
509{
510 struct iface *iface;
511 struct nbr *nbr;
512 struct ctl_nbr *nctl;
513
514 LIST_FOREACH(iface, &oeconf->iface_list, entry)for((iface) = ((&oeconf->iface_list)->lh_first); (iface
)!= ((void *)0); (iface) = ((iface)->entry.le_next))
515 LIST_FOREACH(nbr, &iface->nbr_list, entry)for((nbr) = ((&iface->nbr_list)->lh_first); (nbr)!=
((void *)0); (nbr) = ((nbr)->entry.le_next))
{
516 nctl = nbr_to_ctl(nbr);
517 imsg_compose_event(&c->iev,
518 IMSG_CTL_SHOW_NBR, 0, 0, -1, nctl,
519 sizeof(struct ctl_nbr));
520 }
521
522 imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL((void *)0), 0);
523}
524
525void
526ripe_demote_iface(struct iface *iface, int active)
527{
528 struct demote_msg dmsg;
529
530 if (iface->demote_group[0] == '\0')
531 return;
532
533 bzero(&dmsg, sizeof(dmsg));
534 strlcpy(dmsg.demote_group, iface->demote_group,
535 sizeof(dmsg.demote_group));
536 if (active)
537 dmsg.level = -1;
538 else
539 dmsg.level = 1;
540
541 ripe_imsg_compose_parent(IMSG_DEMOTE, 0, &dmsg, sizeof(dmsg));
542}