Bug Summary

File:src/usr.sbin/ldpd/ldpe.c
Warning:line 385, column 4
Potential memory leak

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ldpe.c -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 -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -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/ldpd/obj -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/usr.sbin/ldpd -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/ldpd/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -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/scan/2024-01-11-140451-98009-1 -x c /usr/src/usr.sbin/ldpd/ldpe.c
1/* $OpenBSD: ldpe.c,v 1.82 2023/12/14 11:10:19 claudio Exp $ */
2
3/*
4 * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
5 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
6 * Copyright (c) 2004, 2008 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 <stdlib.h>
24#include <signal.h>
25#include <string.h>
26#include <pwd.h>
27#include <unistd.h>
28#include <arpa/inet.h>
29#include <errno(*__errno()).h>
30
31#include "ldpd.h"
32#include "ldpe.h"
33#include "lde.h"
34#include "control.h"
35#include "log.h"
36
37static void ldpe_sig_handler(int, short, void *);
38static __dead__attribute__((__noreturn__)) void ldpe_shutdown(void);
39static void ldpe_dispatch_main(int, short, void *);
40static void ldpe_dispatch_lde(int, short, void *);
41static void ldpe_dispatch_pfkey(int, short, void *);
42static void ldpe_setup_sockets(int, int, int, int);
43static void ldpe_close_sockets(int);
44static void ldpe_iface_af_ctl(struct ctl_conn *, int, unsigned int);
45
46struct ldpd_conf *leconf;
47struct ldpd_sysdep sysdep;
48
49static struct imsgev *iev_main;
50static struct imsgev *iev_lde;
51static struct event pfkey_ev;
52
53static void
54ldpe_sig_handler(int sig, short event, void *bula)
55{
56 switch (sig) {
57 case SIGINT2:
58 case SIGTERM15:
59 ldpe_shutdown();
60 /* NOTREACHED */
61 default:
62 fatalx("unexpected signal");
63 }
64}
65
66/* label distribution protocol engine */
67void
68ldpe(int debug, int verbose, char *sockname)
69{
70 struct passwd *pw;
71 struct event ev_sigint, ev_sigterm;
72
73 leconf = config_new_empty();
74
75 log_init(debug);
76 log_verbose(verbose);
77
78 setproctitle("ldp engine");
79 ldpd_process = PROC_LDP_ENGINE;
80 log_procname = "ldpe";
81
82 /* create ldpd control socket outside chroot */
83 global.csock = sockname;
84 if (control_init(global.csock) == -1)
85 fatalx("control socket setup failed");
86
87 LIST_INIT(&global.addr_list)do { ((&global.addr_list)->lh_first) = ((void *)0); } while
(0)
;
88 LIST_INIT(&global.adj_list)do { ((&global.adj_list)->lh_first) = ((void *)0); } while
(0)
;
89 TAILQ_INIT(&global.pending_conns)do { (&global.pending_conns)->tqh_first = ((void *)0);
(&global.pending_conns)->tqh_last = &(&global
.pending_conns)->tqh_first; } while (0)
;
90 if (inet_pton(AF_INET2, AllRouters_v4"224.0.0.2", &global.mcast_addr_v4) != 1)
91 fatal("inet_pton");
92 if (inet_pton(AF_INET624, AllRouters_v6"ff02::2", &global.mcast_addr_v6) != 1)
93 fatal("inet_pton");
94 global.pfkeysock = pfkey_init();
95
96 if ((pw = getpwnam(LDPD_USER"_ldpd")) == NULL((void *)0))
97 fatal("getpwnam");
98
99 if (chroot(pw->pw_dir) == -1)
100 fatal("chroot");
101 if (chdir("/") == -1)
102 fatal("chdir(\"/\")");
103
104 if (setgroups(1, &pw->pw_gid) ||
105 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
106 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
107 fatal("can't drop privileges");
108
109 if (pledge("stdio inet mcast recvfd", NULL((void *)0)) == -1)
110 fatal("pledge");
111
112 event_init();
113 accept_init();
114
115 /* setup signal handler */
116 signal_set(&ev_sigint, SIGINT, ldpe_sig_handler, NULL)event_set(&ev_sigint, 2, 0x08|0x10, ldpe_sig_handler, ((void
*)0))
;
117 signal_set(&ev_sigterm, SIGTERM, ldpe_sig_handler, NULL)event_set(&ev_sigterm, 15, 0x08|0x10, ldpe_sig_handler, (
(void *)0))
;
118 signal_add(&ev_sigint, NULL)event_add(&ev_sigint, ((void *)0));
119 signal_add(&ev_sigterm, NULL)event_add(&ev_sigterm, ((void *)0));
120 signal(SIGPIPE13, SIG_IGN(void (*)(int))1);
121 signal(SIGHUP1, SIG_IGN(void (*)(int))1);
122
123 /* setup pipe and event handler to the parent process */
124 if ((iev_main = malloc(sizeof(struct imsgev))) == NULL((void *)0))
125 fatal(NULL((void *)0));
126 imsg_init(&iev_main->ibuf, 3);
127 iev_main->handler = ldpe_dispatch_main;
128 iev_main->events = EV_READ0x02;
129 event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events,
130 iev_main->handler, iev_main);
131 event_add(&iev_main->ev, NULL((void *)0));
132
133 if (sysdep.no_pfkey == 0) {
134 event_set(&pfkey_ev, global.pfkeysock, EV_READ0x02 | EV_PERSIST0x10,
135 ldpe_dispatch_pfkey, NULL((void *)0));
136 event_add(&pfkey_ev, NULL((void *)0));
137 }
138
139 /* mark sockets as closed */
140 global.ipv4.ldp_disc_socket = -1;
141 global.ipv4.ldp_edisc_socket = -1;
142 global.ipv4.ldp_session_socket = -1;
143 global.ipv6.ldp_disc_socket = -1;
144 global.ipv6.ldp_edisc_socket = -1;
145 global.ipv6.ldp_session_socket = -1;
146
147 /* listen on ldpd control socket */
148 control_listen();
149
150 event_dispatch();
151
152 ldpe_shutdown();
153}
154
155static __dead__attribute__((__noreturn__)) void
156ldpe_shutdown(void)
157{
158 struct if_addr *if_addr;
159 struct adj *adj;
160
161 /* close pipes */
162 msgbuf_write(&iev_lde->ibuf.w);
163 msgbuf_clear(&iev_lde->ibuf.w);
164 close(iev_lde->ibuf.fd);
165 msgbuf_write(&iev_main->ibuf.w);
166 msgbuf_clear(&iev_main->ibuf.w);
167 close(iev_main->ibuf.fd);
168
169 control_cleanup();
170 config_clear(leconf);
171
172 if (sysdep.no_pfkey == 0) {
173 event_del(&pfkey_ev);
174 close(global.pfkeysock);
175 }
176 ldpe_close_sockets(AF_INET2);
177 ldpe_close_sockets(AF_INET624);
178
179 /* remove addresses from global list */
180 while ((if_addr = LIST_FIRST(&global.addr_list)((&global.addr_list)->lh_first)) != NULL((void *)0)) {
181 LIST_REMOVE(if_addr, entry)do { if ((if_addr)->entry.le_next != ((void *)0)) (if_addr
)->entry.le_next->entry.le_prev = (if_addr)->entry.le_prev
; *(if_addr)->entry.le_prev = (if_addr)->entry.le_next;
; ; } while (0)
;
182 free(if_addr);
183 }
184 while ((adj = LIST_FIRST(&global.adj_list)((&global.adj_list)->lh_first)) != NULL((void *)0))
185 adj_del(adj, S_SHUTDOWN0x8000000A);
186
187 /* clean up */
188 free(iev_lde);
189 free(iev_main);
190
191 log_info("ldp engine exiting");
192 exit(0);
193}
194
195/* imesg */
196int
197ldpe_imsg_compose_parent(int type, pid_t pid, void *data, uint16_t datalen)
198{
199 return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen));
200}
201
202int
203ldpe_imsg_compose_lde(int type, uint32_t peerid, pid_t pid, void *data,
204 uint16_t datalen)
205{
206 return (imsg_compose_event(iev_lde, type, peerid, pid, -1,
207 data, datalen));
208}
209
210static void
211ldpe_dispatch_main(int fd, short event, void *bula)
212{
213 static struct ldpd_conf *nconf;
214 struct iface *niface;
215 struct tnbr *ntnbr;
216 struct nbr_params *nnbrp;
217 static struct l2vpn *l2vpn, *nl2vpn;
218 struct l2vpn_if *lif = NULL((void *)0), *nlif;
219 struct l2vpn_pw *npw;
220 struct imsg imsg;
221 struct imsgev *iev = bula;
222 struct imsgbuf *ibuf = &iev->ibuf;
223 struct iface *iface = NULL((void *)0);
224 struct kif *kif;
225 int af;
226 enum socket_type *socket_type;
227 static int disc_socket = -1;
228 static int edisc_socket = -1;
229 static int session_socket = -1;
230 struct nbr *nbr;
231 int n, shut = 0;
232
233 if (event & EV_READ0x02) {
1
Assuming the condition is false
2
Taking false branch
234 if ((n = imsg_read(ibuf)) == -1 && errno(*__errno()) != EAGAIN35)
235 fatal("imsg_read error");
236 if (n == 0) /* connection closed */
237 shut = 1;
238 }
239 if (event & EV_WRITE0x04) {
3
Assuming the condition is false
4
Taking false branch
240 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno(*__errno()) != EAGAIN35)
241 fatal("ldpe_dispatch_main: msgbuf_write");
242 if (n == 0)
243 shut = 1;
244 }
245
246 for (;;) {
5
Loop condition is true. Entering loop body
19
Loop condition is true. Entering loop body
247 if ((n = imsg_get(ibuf, &imsg)) == -1)
6
Assuming the condition is false
7
Taking false branch
20
Assuming the condition is false
21
Taking false branch
248 fatal("ldpe_dispatch_main: imsg_get error");
249 if (n == 0)
8
Assuming 'n' is not equal to 0
9
Taking false branch
22
Assuming 'n' is not equal to 0
23
Taking false branch
250 break;
251
252 switch (imsg.hdr.type) {
10
Control jumps to 'case IMSG_RECONF_CONF:' at line 381
24
Control jumps to 'case IMSG_RECONF_CONF:' at line 381
253 case IMSG_IFSTATUS:
254 if (imsg.hdr.len != IMSG_HEADER_SIZEsizeof(struct imsg_hdr) +
255 sizeof(struct kif))
256 fatalx("IFSTATUS imsg with wrong len");
257 kif = imsg.data;
258
259 iface = if_lookup(leconf, kif->ifindex);
260 if (iface) {
261 iface->flags = kif->flags;
262 iface->linkstate = kif->link_state;
263 if_update(iface, AF_UNSPEC0);
264 break;
265 }
266
267 LIST_FOREACH(l2vpn, &leconf->l2vpn_list, entry)for((l2vpn) = ((&leconf->l2vpn_list)->lh_first); (l2vpn
)!= ((void *)0); (l2vpn) = ((l2vpn)->entry.le_next))
{
268 lif = l2vpn_if_find(l2vpn, kif->ifindex);
269 if (lif) {
270 lif->flags = kif->flags;
271 lif->linkstate = kif->link_state;
272 memcpy(lif->mac, kif->mac,
273 sizeof(lif->mac));
274 l2vpn_if_update(lif);
275 break;
276 }
277 }
278 break;
279 case IMSG_NEWADDR:
280 if (imsg.hdr.len != IMSG_HEADER_SIZEsizeof(struct imsg_hdr) +
281 sizeof(struct kaddr))
282 fatalx("NEWADDR imsg with wrong len");
283
284 if_addr_add(imsg.data);
285 break;
286 case IMSG_DELADDR:
287 if (imsg.hdr.len != IMSG_HEADER_SIZEsizeof(struct imsg_hdr) +
288 sizeof(struct kaddr))
289 fatalx("DELADDR imsg with wrong len");
290
291 if_addr_del(imsg.data);
292 break;
293 case IMSG_SOCKET_IPC:
294 if (iev_lde) {
295 log_warnx("%s: received unexpected imsg fd "
296 "to lde", __func__);
297 break;
298 }
299 if ((fd = imsg_get_fd(&imsg)) == -1) {
300 log_warnx("%s: expected to receive imsg fd to "
301 "lde but didn't receive any", __func__);
302 break;
303 }
304
305 if ((iev_lde = malloc(sizeof(struct imsgev))) == NULL((void *)0))
306 fatal(NULL((void *)0));
307 imsg_init(&iev_lde->ibuf, fd);
308 iev_lde->handler = ldpe_dispatch_lde;
309 iev_lde->events = EV_READ0x02;
310 event_set(&iev_lde->ev, iev_lde->ibuf.fd,
311 iev_lde->events, iev_lde->handler, iev_lde);
312 event_add(&iev_lde->ev, NULL((void *)0));
313 break;
314 case IMSG_CLOSE_SOCKETS:
315 af = imsg.hdr.peerid;
316
317 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id)for ((nbr) = nbr_id_head_RB_MINMAX(&nbrs_by_id, -1); (nbr
) != ((void *)0); (nbr) = nbr_id_head_RB_NEXT(nbr))
{
318 if (nbr->af != af)
319 continue;
320 session_shutdown(nbr, S_SHUTDOWN0x8000000A, 0, 0);
321 pfkey_remove(nbr);
322 }
323 ldpe_close_sockets(af);
324 if_update_all(af);
325 tnbr_update_all(af);
326
327 disc_socket = -1;
328 edisc_socket = -1;
329 session_socket = -1;
330 if ((ldp_af_conf_get(leconf, af))->flags &
331 F_LDPD_AF_ENABLED0x0001)
332 ldpe_imsg_compose_parent(IMSG_REQUEST_SOCKETS,
333 af, NULL((void *)0), 0);
334 break;
335 case IMSG_SOCKET_NET:
336 if (imsg.hdr.len != IMSG_HEADER_SIZEsizeof(struct imsg_hdr) +
337 sizeof(enum socket_type))
338 fatalx("SOCKET_NET imsg with wrong len");
339 socket_type = imsg.data;
340
341 switch (*socket_type) {
342 case LDP_SOCKET_DISC:
343 disc_socket = imsg_get_fd(&imsg);
344 break;
345 case LDP_SOCKET_EDISC:
346 edisc_socket = imsg_get_fd(&imsg);
347 break;
348 case LDP_SOCKET_SESSION:
349 session_socket = imsg_get_fd(&imsg);
350 break;
351 }
352 break;
353 case IMSG_SETUP_SOCKETS:
354 af = imsg.hdr.peerid;
355 if (disc_socket == -1 || edisc_socket == -1 ||
356 session_socket == -1) {
357 if (disc_socket != -1)
358 close(disc_socket);
359 if (edisc_socket != -1)
360 close(edisc_socket);
361 if (session_socket != -1)
362 close(session_socket);
363 break;
364 }
365
366 ldpe_setup_sockets(af, disc_socket, edisc_socket,
367 session_socket);
368 if_update_all(af);
369 tnbr_update_all(af);
370 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id)for ((nbr) = nbr_id_head_RB_MINMAX(&nbrs_by_id, -1); (nbr
) != ((void *)0); (nbr) = nbr_id_head_RB_NEXT(nbr))
{
371 if (nbr->af != af)
372 continue;
373 nbr->laddr = (ldp_af_conf_get(leconf,
374 af))->trans_addr;
375 if (pfkey_establish(nconf, nbr) == -1)
376 fatalx("pfkey setup failed");
377 if (nbr_session_active_role(nbr))
378 nbr_establish_connection(nbr);
379 }
380 break;
381 case IMSG_RECONF_CONF:
382 if ((nconf = malloc(sizeof(struct ldpd_conf))) ==
11
Memory is allocated
12
Assuming the condition is false
13
Taking false branch
25
Assuming the condition is false
26
Taking false branch
383 NULL((void *)0))
384 fatal(NULL((void *)0));
385 memcpy(nconf, imsg.data, sizeof(struct ldpd_conf));
27
Potential memory leak
386
387 LIST_INIT(&nconf->iface_list)do { ((&nconf->iface_list)->lh_first) = ((void *)0)
; } while (0)
;
14
Loop condition is false. Exiting loop
388 LIST_INIT(&nconf->tnbr_list)do { ((&nconf->tnbr_list)->lh_first) = ((void *)0);
} while (0)
;
15
Loop condition is false. Exiting loop
389 LIST_INIT(&nconf->nbrp_list)do { ((&nconf->nbrp_list)->lh_first) = ((void *)0);
} while (0)
;
16
Loop condition is false. Exiting loop
390 LIST_INIT(&nconf->l2vpn_list)do { ((&nconf->l2vpn_list)->lh_first) = ((void *)0)
; } while (0)
;
17
Loop condition is false. Exiting loop
391 LIST_INIT(&nconf->auth_list)do { ((&nconf->auth_list)->lh_first) = ((void *)0);
} while (0)
;
18
Loop condition is false. Exiting loop
392 break;
393 case IMSG_RECONF_IFACE:
394 if ((niface = malloc(sizeof(struct iface))) == NULL((void *)0))
395 fatal(NULL((void *)0));
396 memcpy(niface, imsg.data, sizeof(struct iface));
397
398 LIST_INIT(&niface->addr_list)do { ((&niface->addr_list)->lh_first) = ((void *)0)
; } while (0)
;
399 LIST_INIT(&niface->ipv4.adj_list)do { ((&niface->ipv4.adj_list)->lh_first) = ((void *
)0); } while (0)
;
400 LIST_INIT(&niface->ipv6.adj_list)do { ((&niface->ipv6.adj_list)->lh_first) = ((void *
)0); } while (0)
;
401 niface->ipv4.iface = niface;
402 niface->ipv6.iface = niface;
403
404 LIST_INSERT_HEAD(&nconf->iface_list, niface, entry)do { if (((niface)->entry.le_next = (&nconf->iface_list
)->lh_first) != ((void *)0)) (&nconf->iface_list)->
lh_first->entry.le_prev = &(niface)->entry.le_next;
(&nconf->iface_list)->lh_first = (niface); (niface
)->entry.le_prev = &(&nconf->iface_list)->lh_first
; } while (0)
;
405 break;
406 case IMSG_RECONF_TNBR:
407 if ((ntnbr = malloc(sizeof(struct tnbr))) == NULL((void *)0))
408 fatal(NULL((void *)0));
409 memcpy(ntnbr, imsg.data, sizeof(struct tnbr));
410
411 LIST_INSERT_HEAD(&nconf->tnbr_list, ntnbr, entry)do { if (((ntnbr)->entry.le_next = (&nconf->tnbr_list
)->lh_first) != ((void *)0)) (&nconf->tnbr_list)->
lh_first->entry.le_prev = &(ntnbr)->entry.le_next; (
&nconf->tnbr_list)->lh_first = (ntnbr); (ntnbr)->
entry.le_prev = &(&nconf->tnbr_list)->lh_first;
} while (0)
;
412 break;
413 case IMSG_RECONF_NBRP:
414 if ((nnbrp = malloc(sizeof(struct nbr_params))) == NULL((void *)0))
415 fatal(NULL((void *)0));
416 memcpy(nnbrp, imsg.data, sizeof(struct nbr_params));
417
418 LIST_INSERT_HEAD(&nconf->nbrp_list, nnbrp, entry)do { if (((nnbrp)->entry.le_next = (&nconf->nbrp_list
)->lh_first) != ((void *)0)) (&nconf->nbrp_list)->
lh_first->entry.le_prev = &(nnbrp)->entry.le_next; (
&nconf->nbrp_list)->lh_first = (nnbrp); (nnbrp)->
entry.le_prev = &(&nconf->nbrp_list)->lh_first;
} while (0)
;
419 break;
420 case IMSG_RECONF_L2VPN:
421 if ((nl2vpn = malloc(sizeof(struct l2vpn))) == NULL((void *)0))
422 fatal(NULL((void *)0));
423 memcpy(nl2vpn, imsg.data, sizeof(struct l2vpn));
424
425 LIST_INIT(&nl2vpn->if_list)do { ((&nl2vpn->if_list)->lh_first) = ((void *)0); }
while (0)
;
426 LIST_INIT(&nl2vpn->pw_list)do { ((&nl2vpn->pw_list)->lh_first) = ((void *)0); }
while (0)
;
427
428 LIST_INSERT_HEAD(&nconf->l2vpn_list, nl2vpn, entry)do { if (((nl2vpn)->entry.le_next = (&nconf->l2vpn_list
)->lh_first) != ((void *)0)) (&nconf->l2vpn_list)->
lh_first->entry.le_prev = &(nl2vpn)->entry.le_next;
(&nconf->l2vpn_list)->lh_first = (nl2vpn); (nl2vpn
)->entry.le_prev = &(&nconf->l2vpn_list)->lh_first
; } while (0)
;
429 break;
430 case IMSG_RECONF_L2VPN_IF:
431 if ((nlif = malloc(sizeof(struct l2vpn_if))) == NULL((void *)0))
432 fatal(NULL((void *)0));
433 memcpy(nlif, imsg.data, sizeof(struct l2vpn_if));
434
435 nlif->l2vpn = nl2vpn;
436 LIST_INSERT_HEAD(&nl2vpn->if_list, nlif, entry)do { if (((nlif)->entry.le_next = (&nl2vpn->if_list
)->lh_first) != ((void *)0)) (&nl2vpn->if_list)->
lh_first->entry.le_prev = &(nlif)->entry.le_next; (
&nl2vpn->if_list)->lh_first = (nlif); (nlif)->entry
.le_prev = &(&nl2vpn->if_list)->lh_first; } while
(0)
;
437 break;
438 case IMSG_RECONF_L2VPN_PW:
439 if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL((void *)0))
440 fatal(NULL((void *)0));
441 memcpy(npw, imsg.data, sizeof(struct l2vpn_pw));
442
443 npw->l2vpn = nl2vpn;
444 LIST_INSERT_HEAD(&nl2vpn->pw_list, npw, entry)do { if (((npw)->entry.le_next = (&nl2vpn->pw_list)
->lh_first) != ((void *)0)) (&nl2vpn->pw_list)->
lh_first->entry.le_prev = &(npw)->entry.le_next; (&
nl2vpn->pw_list)->lh_first = (npw); (npw)->entry.le_prev
= &(&nl2vpn->pw_list)->lh_first; } while (0)
;
445 break;
446 case IMSG_RECONF_CONF_AUTH: {
447 struct ldp_auth *auth;
448
449 auth = malloc(sizeof(*auth));
450 if (auth == NULL((void *)0))
451 fatal(NULL((void *)0));
452
453 memcpy(auth, imsg.data, sizeof(*auth));
454
455 LIST_INSERT_HEAD(&nconf->auth_list, auth, entry)do { if (((auth)->entry.le_next = (&nconf->auth_list
)->lh_first) != ((void *)0)) (&nconf->auth_list)->
lh_first->entry.le_prev = &(auth)->entry.le_next; (
&nconf->auth_list)->lh_first = (auth); (auth)->entry
.le_prev = &(&nconf->auth_list)->lh_first; } while
(0)
;
456 break;
457 }
458
459 case IMSG_RECONF_END:
460 merge_config(leconf, nconf);
461 nconf = NULL((void *)0);
462 global.conf_seqnum++;
463 break;
464 case IMSG_CTL_KROUTE:
465 case IMSG_CTL_KROUTE_ADDR:
466 case IMSG_CTL_IFINFO:
467 case IMSG_CTL_END:
468 control_imsg_relay(&imsg);
469 break;
470 default:
471 log_debug("ldpe_dispatch_main: error handling imsg %d",
472 imsg.hdr.type);
473 break;
474 }
475 imsg_free(&imsg);
476 }
477 if (!shut)
478 imsg_event_add(iev);
479 else {
480 /* this pipe is dead, so remove the event handler */
481 event_del(&iev->ev);
482 event_loopexit(NULL((void *)0));
483 }
484}
485
486static void
487ldpe_dispatch_lde(int fd, short event, void *bula)
488{
489 struct imsgev *iev = bula;
490 struct imsgbuf *ibuf = &iev->ibuf;
491 struct imsg imsg;
492 struct map map;
493 struct notify_msg nm;
494 int n, shut = 0;
495 struct nbr *nbr = NULL((void *)0);
496
497 if (event & EV_READ0x02) {
498 if ((n = imsg_read(ibuf)) == -1 && errno(*__errno()) != EAGAIN35)
499 fatal("imsg_read error");
500 if (n == 0) /* connection closed */
501 shut = 1;
502 }
503 if (event & EV_WRITE0x04) {
504 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno(*__errno()) != EAGAIN35)
505 fatal("ldpe_dispatch_lde: msgbuf_write");
506 if (n == 0)
507 shut = 1;
508 }
509
510 for (;;) {
511 if ((n = imsg_get(ibuf, &imsg)) == -1)
512 fatal("ldpe_dispatch_lde: imsg_get error");
513 if (n == 0)
514 break;
515
516 switch (imsg.hdr.type) {
517 case IMSG_MAPPING_ADD:
518 case IMSG_RELEASE_ADD:
519 case IMSG_REQUEST_ADD:
520 case IMSG_WITHDRAW_ADD:
521 if (imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr) != sizeof(map))
522 fatalx("invalid size of map request");
523 memcpy(&map, imsg.data, sizeof(map));
524
525 nbr = nbr_find_peerid(imsg.hdr.peerid);
526 if (nbr == NULL((void *)0)) {
527 log_debug("ldpe_dispatch_lde: cannot find "
528 "neighbor");
529 break;
530 }
531 if (nbr->state != NBR_STA_OPER0x0010)
532 break;
533
534 switch (imsg.hdr.type) {
535 case IMSG_MAPPING_ADD:
536 mapping_list_add(&nbr->mapping_list, &map);
537 break;
538 case IMSG_RELEASE_ADD:
539 mapping_list_add(&nbr->release_list, &map);
540 break;
541 case IMSG_REQUEST_ADD:
542 mapping_list_add(&nbr->request_list, &map);
543 break;
544 case IMSG_WITHDRAW_ADD:
545 mapping_list_add(&nbr->withdraw_list, &map);
546 break;
547 }
548 break;
549 case IMSG_MAPPING_ADD_END:
550 case IMSG_RELEASE_ADD_END:
551 case IMSG_REQUEST_ADD_END:
552 case IMSG_WITHDRAW_ADD_END:
553 nbr = nbr_find_peerid(imsg.hdr.peerid);
554 if (nbr == NULL((void *)0)) {
555 log_debug("ldpe_dispatch_lde: cannot find "
556 "neighbor");
557 break;
558 }
559 if (nbr->state != NBR_STA_OPER0x0010)
560 break;
561
562 switch (imsg.hdr.type) {
563 case IMSG_MAPPING_ADD_END:
564 send_labelmessage(nbr, MSG_TYPE_LABELMAPPING0x0400,
565 &nbr->mapping_list);
566 break;
567 case IMSG_RELEASE_ADD_END:
568 send_labelmessage(nbr, MSG_TYPE_LABELRELEASE0x0403,
569 &nbr->release_list);
570 break;
571 case IMSG_REQUEST_ADD_END:
572 send_labelmessage(nbr, MSG_TYPE_LABELREQUEST0x0401,
573 &nbr->request_list);
574 break;
575 case IMSG_WITHDRAW_ADD_END:
576 send_labelmessage(nbr, MSG_TYPE_LABELWITHDRAW0x0402,
577 &nbr->withdraw_list);
578 break;
579 }
580 break;
581 case IMSG_NOTIFICATION_SEND:
582 if (imsg.hdr.len - IMSG_HEADER_SIZEsizeof(struct imsg_hdr) != sizeof(nm))
583 fatalx("invalid size of OE request");
584 memcpy(&nm, imsg.data, sizeof(nm));
585
586 nbr = nbr_find_peerid(imsg.hdr.peerid);
587 if (nbr == NULL((void *)0)) {
588 log_debug("ldpe_dispatch_lde: cannot find "
589 "neighbor");
590 break;
591 }
592 if (nbr->state != NBR_STA_OPER0x0010)
593 break;
594
595 send_notification_full(nbr->tcp, &nm);
596 break;
597 case IMSG_CTL_END:
598 case IMSG_CTL_SHOW_LIB:
599 case IMSG_CTL_SHOW_L2VPN_PW:
600 case IMSG_CTL_SHOW_L2VPN_BINDING:
601 control_imsg_relay(&imsg);
602 break;
603 default:
604 log_debug("ldpe_dispatch_lde: error handling imsg %d",
605 imsg.hdr.type);
606 break;
607 }
608 imsg_free(&imsg);
609 }
610 if (!shut)
611 imsg_event_add(iev);
612 else {
613 /* this pipe is dead, so remove the event handler */
614 event_del(&iev->ev);
615 event_loopexit(NULL((void *)0));
616 }
617}
618
619static void
620ldpe_dispatch_pfkey(int fd, short event, void *bula)
621{
622 if (event & EV_READ0x02) {
623 if (pfkey_read(fd, NULL((void *)0)) == -1) {
624 fatal("pfkey_read failed, exiting...");
625 }
626 }
627}
628
629static void
630ldpe_setup_sockets(int af, int disc_socket, int edisc_socket,
631 int session_socket)
632{
633 struct ldpd_af_global *af_global;
634
635 af_global = ldp_af_global_get(&global, af);
636
637 /* discovery socket */
638 af_global->ldp_disc_socket = disc_socket;
639 event_set(&af_global->disc_ev, af_global->ldp_disc_socket,
640 EV_READ0x02|EV_PERSIST0x10, disc_recv_packet, NULL((void *)0));
641 event_add(&af_global->disc_ev, NULL((void *)0));
642
643 /* extended discovery socket */
644 af_global->ldp_edisc_socket = edisc_socket;
645 event_set(&af_global->edisc_ev, af_global->ldp_edisc_socket,
646 EV_READ0x02|EV_PERSIST0x10, disc_recv_packet, NULL((void *)0));
647 event_add(&af_global->edisc_ev, NULL((void *)0));
648
649 /* session socket */
650 af_global->ldp_session_socket = session_socket;
651 accept_add(af_global->ldp_session_socket, session_accept, NULL((void *)0));
652}
653
654static void
655ldpe_close_sockets(int af)
656{
657 struct ldpd_af_global *af_global;
658
659 af_global = ldp_af_global_get(&global, af);
660
661 /* discovery socket */
662 if (event_initialized(&af_global->disc_ev)((&af_global->disc_ev)->ev_flags & 0x80))
663 event_del(&af_global->disc_ev);
664 if (af_global->ldp_disc_socket != -1) {
665 close(af_global->ldp_disc_socket);
666 af_global->ldp_disc_socket = -1;
667 }
668
669 /* extended discovery socket */
670 if (event_initialized(&af_global->edisc_ev)((&af_global->edisc_ev)->ev_flags & 0x80))
671 event_del(&af_global->edisc_ev);
672 if (af_global->ldp_edisc_socket != -1) {
673 close(af_global->ldp_edisc_socket);
674 af_global->ldp_edisc_socket = -1;
675 }
676
677 /* session socket */
678 if (af_global->ldp_session_socket != -1) {
679 accept_del(af_global->ldp_session_socket);
680 close(af_global->ldp_session_socket);
681 af_global->ldp_session_socket = -1;
682 }
683}
684
685void
686ldpe_reset_nbrs(int af)
687{
688 struct nbr *nbr;
689
690 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id)for ((nbr) = nbr_id_head_RB_MINMAX(&nbrs_by_id, -1); (nbr
) != ((void *)0); (nbr) = nbr_id_head_RB_NEXT(nbr))
{
691 if (nbr->af == af)
692 session_shutdown(nbr, S_SHUTDOWN0x8000000A, 0, 0);
693 }
694}
695
696void
697ldpe_reset_ds_nbrs(void)
698{
699 struct nbr *nbr;
700
701 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id)for ((nbr) = nbr_id_head_RB_MINMAX(&nbrs_by_id, -1); (nbr
) != ((void *)0); (nbr) = nbr_id_head_RB_NEXT(nbr))
{
702 if (nbr->ds_tlv)
703 session_shutdown(nbr, S_SHUTDOWN0x8000000A, 0, 0);
704 }
705}
706
707void
708ldpe_remove_dynamic_tnbrs(int af)
709{
710 struct tnbr *tnbr, *safe;
711
712 LIST_FOREACH_SAFE(tnbr, &leconf->tnbr_list, entry, safe)for ((tnbr) = ((&leconf->tnbr_list)->lh_first); (tnbr
) && ((safe) = ((tnbr)->entry.le_next), 1); (tnbr)
= (safe))
{
713 if (tnbr->af != af)
714 continue;
715
716 tnbr->flags &= ~F_TNBR_DYNAMIC0x02;
717 tnbr_check(tnbr);
718 }
719}
720
721void
722ldpe_stop_init_backoff(int af)
723{
724 struct nbr *nbr;
725
726 RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id)for ((nbr) = nbr_id_head_RB_MINMAX(&nbrs_by_id, -1); (nbr
) != ((void *)0); (nbr) = nbr_id_head_RB_NEXT(nbr))
{
727 if (nbr->af == af && nbr_pending_idtimer(nbr)) {
728 nbr_stop_idtimer(nbr);
729 nbr_establish_connection(nbr);
730 }
731 }
732}
733
734static void
735ldpe_iface_af_ctl(struct ctl_conn *c, int af, unsigned int idx)
736{
737 struct iface *iface;
738 struct iface_af *ia;
739 struct ctl_iface *ictl;
740
741 LIST_FOREACH(iface, &leconf->iface_list, entry)for((iface) = ((&leconf->iface_list)->lh_first); (iface
)!= ((void *)0); (iface) = ((iface)->entry.le_next))
{
742 if (idx == 0 || idx == iface->ifindex) {
743 ia = iface_af_get(iface, af);
744 if (!ia->enabled)
745 continue;
746
747 ictl = if_to_ctl(ia);
748 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_INTERFACE,
749 0, 0, -1, ictl, sizeof(struct ctl_iface));
750 }
751 }
752}
753
754void
755ldpe_iface_ctl(struct ctl_conn *c, unsigned int idx)
756{
757 ldpe_iface_af_ctl(c, AF_INET2, idx);
758 ldpe_iface_af_ctl(c, AF_INET624, idx);
759}
760
761void
762ldpe_adj_ctl(struct ctl_conn *c)
763{
764 struct nbr *nbr;
765 struct adj *adj;
766 struct ctl_adj *actl;
767
768 RB_FOREACH(nbr, nbr_addr_head, &nbrs_by_addr)for ((nbr) = nbr_addr_head_RB_MINMAX(&nbrs_by_addr, -1); (
nbr) != ((void *)0); (nbr) = nbr_addr_head_RB_NEXT(nbr))
{
769 LIST_FOREACH(adj, &nbr->adj_list, nbr_entry)for((adj) = ((&nbr->adj_list)->lh_first); (adj)!= (
(void *)0); (adj) = ((adj)->nbr_entry.le_next))
{
770 actl = adj_to_ctl(adj);
771 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISCOVERY,
772 0, 0, -1, actl, sizeof(struct ctl_adj));
773 }
774 }
775 /* show adjacencies not associated with any neighbor */
776 LIST_FOREACH(adj, &global.adj_list, global_entry)for((adj) = ((&global.adj_list)->lh_first); (adj)!= ((
void *)0); (adj) = ((adj)->global_entry.le_next))
{
777 if (adj->nbr != NULL((void *)0))
778 continue;
779
780 actl = adj_to_ctl(adj);
781 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISCOVERY, 0, 0,
782 -1, actl, sizeof(struct ctl_adj));
783 }
784
785 imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL((void *)0), 0);
786}
787
788void
789ldpe_nbr_ctl(struct ctl_conn *c)
790{
791 struct nbr *nbr;
792 struct ctl_nbr *nctl;
793
794 RB_FOREACH(nbr, nbr_addr_head, &nbrs_by_addr)for ((nbr) = nbr_addr_head_RB_MINMAX(&nbrs_by_addr, -1); (
nbr) != ((void *)0); (nbr) = nbr_addr_head_RB_NEXT(nbr))
{
795 nctl = nbr_to_ctl(nbr);
796 imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR, 0, 0, -1, nctl,
797 sizeof(struct ctl_nbr));
798 }
799 imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL((void *)0), 0);
800}
801
802void
803mapping_list_add(struct mapping_head *mh, struct map *map)
804{
805 struct mapping_entry *me;
806
807 me = calloc(1, sizeof(*me));
808 if (me == NULL((void *)0))
809 fatal(__func__);
810 me->map = *map;
811
812 TAILQ_INSERT_TAIL(mh, me, entry)do { (me)->entry.tqe_next = ((void *)0); (me)->entry.tqe_prev
= (mh)->tqh_last; *(mh)->tqh_last = (me); (mh)->tqh_last
= &(me)->entry.tqe_next; } while (0)
;
813}
814
815void
816mapping_list_clr(struct mapping_head *mh)
817{
818 struct mapping_entry *me;
819
820 while ((me = TAILQ_FIRST(mh)((mh)->tqh_first)) != NULL((void *)0)) {
821 TAILQ_REMOVE(mh, me, entry)do { if (((me)->entry.tqe_next) != ((void *)0)) (me)->entry
.tqe_next->entry.tqe_prev = (me)->entry.tqe_prev; else (
mh)->tqh_last = (me)->entry.tqe_prev; *(me)->entry.tqe_prev
= (me)->entry.tqe_next; ; ; } while (0)
;
822 free(me);
823 }
824}