File: | src/usr.sbin/ripd/ripe.c |
Warning: | line 443, column 7 Potential leak of memory pointed to by 'rr' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | ||||
45 | void ripe_sig_handler(int, short, void *); | |||
46 | __dead__attribute__((__noreturn__)) void ripe_shutdown(void); | |||
47 | ||||
48 | struct ripd_conf *oeconf = NULL((void *)0); | |||
49 | static struct imsgev *iev_main; | |||
50 | static struct imsgev *iev_rde; | |||
51 | ||||
52 | /* ARGSUSED */ | |||
53 | void | |||
54 | ripe_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 */ | |||
67 | pid_t | |||
68 | ripe(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 | ||||
209 | int | |||
210 | ripe_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 | ||||
215 | int | |||
216 | ripe_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 */ | |||
224 | void | |||
225 | ripe_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 */ | |||
303 | void | |||
304 | ripe_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) { | |||
| ||||
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) { | |||
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 (;;) { | |||
329 | if ((n = imsg_get(ibuf, &imsg)) == -1) | |||
330 | fatal("ripe_dispatch_rde: imsg_get error"); | |||
331 | if (n == 0) | |||
332 | break; | |||
333 | ||||
334 | switch (imsg.hdr.type) { | |||
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)) | |||
378 | fatalx("invalid size of RDE request"); | |||
379 | ||||
380 | if ((rr = malloc(sizeof(*rr))) == NULL((void *)0)) | |||
381 | fatal("ripe_dispatch_rde"); | |||
382 | ||||
383 | memcpy(rr, imsg.data, sizeof(*rr)); | |||
384 | ||||
385 | if (imsg.hdr.peerid == 0) { | |||
386 | LIST_FOREACH(iface, &oeconf->iface_list, entry)for((iface) = ((&oeconf->iface_list)->lh_first); (iface )!= ((void *)0); (iface) = ((iface)->entry.le_next)) | |||
387 | add_entry(&iface->rp_list, rr); | |||
388 | ||||
389 | break; | |||
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) | |||
| ||||
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 | |||
453 | ripe_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 | ||||
492 | void | |||
493 | ripe_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 | ||||
507 | void | |||
508 | ripe_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 | ||||
525 | void | |||
526 | ripe_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 | } |