]>
Commit | Line | Data |
---|---|---|
8429abe0 RW |
1 | /* $OpenBSD$ */ |
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 | ||
eac6e3f0 | 22 | #include <zebra.h> |
8429abe0 RW |
23 | |
24 | #include "ldpd.h" | |
25 | #include "ldpe.h" | |
26 | #include "lde.h" | |
27 | #include "control.h" | |
28 | #include "log.h" | |
eac6e3f0 RW |
29 | #include "ldp_debug.h" |
30 | ||
31 | #include <lib/log.h> | |
32 | #include "memory.h" | |
33 | #include "privs.h" | |
34 | #include "sigevent.h" | |
35 | ||
36 | static void ldpe_shutdown(void); | |
37 | static int ldpe_dispatch_main(struct thread *); | |
38 | static int ldpe_dispatch_lde(struct thread *); | |
39 | #ifdef __OpenBSD__ | |
40 | static int ldpe_dispatch_pfkey(struct thread *); | |
41 | #endif | |
8429abe0 RW |
42 | static void ldpe_setup_sockets(int, int, int, int); |
43 | static void ldpe_close_sockets(int); | |
6cd8093d | 44 | static void ldpe_iface_af_ctl(struct ctl_conn *c, int af, ifindex_t ifidx); |
2d1aa1e8 | 45 | static void ldpe_check_filter_af(int, struct ldpd_af_conf *, const char *); |
8429abe0 RW |
46 | |
47 | struct ldpd_conf *leconf; | |
eac6e3f0 | 48 | #ifdef __OpenBSD__ |
8429abe0 | 49 | struct ldpd_sysdep sysdep; |
eac6e3f0 | 50 | #endif |
8429abe0 | 51 | |
91191fa2 | 52 | static struct imsgev iev_main_data; |
28e8294c | 53 | static struct imsgev *iev_main, *iev_main_sync; |
8429abe0 | 54 | static struct imsgev *iev_lde; |
eac6e3f0 RW |
55 | #ifdef __OpenBSD__ |
56 | static struct thread *pfkey_ev; | |
57 | #endif | |
8429abe0 | 58 | |
eac6e3f0 RW |
59 | /* ldpe privileges */ |
60 | static zebra_capabilities_t _caps_p [] = | |
61 | { | |
62 | ZCAP_BIND, | |
63 | ZCAP_NET_ADMIN | |
64 | }; | |
65 | ||
66 | struct zebra_privs_t ldpe_privs = | |
67 | { | |
eac6e3f0 RW |
68 | #if defined(VTY_GROUP) |
69 | .vty_group = VTY_GROUP, | |
70 | #endif | |
71 | .caps_p = _caps_p, | |
72 | .cap_num_p = array_size(_caps_p), | |
73 | .cap_num_i = 0 | |
74 | }; | |
75 | ||
76 | /* SIGINT / SIGTERM handler. */ | |
8429abe0 | 77 | static void |
eac6e3f0 | 78 | sigint(void) |
8429abe0 | 79 | { |
eac6e3f0 | 80 | ldpe_shutdown(); |
8429abe0 RW |
81 | } |
82 | ||
eac6e3f0 RW |
83 | static struct quagga_signal_t ldpe_signals[] = |
84 | { | |
1e7e440f RW |
85 | { |
86 | .signal = SIGHUP, | |
87 | /* ignore */ | |
88 | }, | |
eac6e3f0 RW |
89 | { |
90 | .signal = SIGINT, | |
91 | .handler = &sigint, | |
92 | }, | |
93 | { | |
94 | .signal = SIGTERM, | |
95 | .handler = &sigint, | |
96 | }, | |
97 | }; | |
98 | ||
56b7d725 RK |
99 | char *pkt_ptr; /* packet buffer */ |
100 | ||
8429abe0 RW |
101 | /* label distribution protocol engine */ |
102 | void | |
274f5abf | 103 | ldpe(void) |
8429abe0 | 104 | { |
eac6e3f0 | 105 | struct thread thread; |
8429abe0 | 106 | |
eac6e3f0 | 107 | #ifdef HAVE_SETPROCTITLE |
8429abe0 | 108 | setproctitle("ldp engine"); |
eac6e3f0 | 109 | #endif |
8429abe0 | 110 | ldpd_process = PROC_LDP_ENGINE; |
fa68f9da | 111 | log_procname = log_procnames[ldpd_process]; |
8429abe0 | 112 | |
972a411c | 113 | master = thread_master_create(NULL); |
8429abe0 RW |
114 | |
115 | /* setup signal handler */ | |
eac6e3f0 | 116 | signal_init(master, array_size(ldpe_signals), ldpe_signals); |
8429abe0 | 117 | |
28e8294c RW |
118 | /* setup pipes and event handlers to the parent process */ |
119 | if ((iev_main = calloc(1, sizeof(struct imsgev))) == NULL) | |
8429abe0 | 120 | fatal(NULL); |
28e8294c | 121 | imsg_init(&iev_main->ibuf, LDPD_FD_ASYNC); |
eac6e3f0 | 122 | iev_main->handler_read = ldpe_dispatch_main; |
66e78ae6 QY |
123 | iev_main->ev_read = NULL; |
124 | thread_add_read(master, iev_main->handler_read, iev_main, iev_main->ibuf.fd, | |
125 | &iev_main->ev_read); | |
eac6e3f0 | 126 | iev_main->handler_write = ldp_write_handler; |
28e8294c | 127 | |
91191fa2 DS |
128 | memset(&iev_main_data, 0, sizeof(iev_main_data)); |
129 | iev_main_sync = &iev_main_data; | |
28e8294c | 130 | imsg_init(&iev_main_sync->ibuf, LDPD_FD_SYNC); |
eac6e3f0 | 131 | |
274f5abf RW |
132 | /* create base configuration */ |
133 | leconf = config_new_empty(); | |
134 | ||
135 | /* Fetch next active thread. */ | |
136 | while (thread_fetch(master, &thread)) | |
137 | thread_call(&thread); | |
138 | } | |
139 | ||
140 | void | |
141 | ldpe_init(struct ldpd_init *init) | |
142 | { | |
f43be00b RZ |
143 | #ifdef __OpenBSD__ |
144 | /* This socket must be open before dropping privileges. */ | |
145 | global.pfkeysock = pfkey_init(); | |
146 | if (sysdep.no_pfkey == 0) { | |
147 | pfkey_ev = NULL; | |
148 | thread_add_read(master, ldpe_dispatch_pfkey, NULL, global.pfkeysock, | |
149 | &pfkey_ev); | |
150 | } | |
151 | #endif | |
152 | ||
274f5abf | 153 | /* drop privileges */ |
af7e63a3 RW |
154 | ldpe_privs.user = init->user; |
155 | ldpe_privs.group = init->group; | |
37a1f2fb | 156 | zprivs_preinit(&ldpe_privs); |
274f5abf RW |
157 | zprivs_init(&ldpe_privs); |
158 | ||
159 | /* listen on ldpd control socket */ | |
160 | strlcpy(ctl_sock_path, init->ctl_sock_path, sizeof(ctl_sock_path)); | |
161 | if (control_init(ctl_sock_path) == -1) | |
162 | fatalx("control socket setup failed"); | |
163 | TAILQ_INIT(&ctl_conns); | |
164 | control_listen(); | |
165 | ||
274f5abf | 166 | LIST_INIT(&global.addr_list); |
45926e58 | 167 | RB_INIT(global_adj_head, &global.adj_tree); |
274f5abf RW |
168 | TAILQ_INIT(&global.pending_conns); |
169 | if (inet_pton(AF_INET, AllRouters_v4, &global.mcast_addr_v4) != 1) | |
170 | fatal("inet_pton"); | |
171 | if (inet_pton(AF_INET6, AllRouters_v6, &global.mcast_addr_v6) != 1) | |
172 | fatal("inet_pton"); | |
8429abe0 RW |
173 | |
174 | /* mark sockets as closed */ | |
175 | global.ipv4.ldp_disc_socket = -1; | |
176 | global.ipv4.ldp_edisc_socket = -1; | |
177 | global.ipv4.ldp_session_socket = -1; | |
178 | global.ipv6.ldp_disc_socket = -1; | |
179 | global.ipv6.ldp_edisc_socket = -1; | |
180 | global.ipv6.ldp_session_socket = -1; | |
181 | ||
8429abe0 RW |
182 | if ((pkt_ptr = calloc(1, IBUF_READ_SIZE)) == NULL) |
183 | fatal(__func__); | |
184 | ||
274f5abf | 185 | accept_init(); |
8429abe0 RW |
186 | } |
187 | ||
eac6e3f0 | 188 | static void |
8429abe0 RW |
189 | ldpe_shutdown(void) |
190 | { | |
191 | struct if_addr *if_addr; | |
192 | struct adj *adj; | |
193 | ||
194 | /* close pipes */ | |
835a7376 | 195 | if (iev_lde) { |
835a7376 RW |
196 | msgbuf_clear(&iev_lde->ibuf.w); |
197 | close(iev_lde->ibuf.fd); | |
50732983 | 198 | iev_lde->ibuf.fd = -1; |
835a7376 | 199 | } |
8429abe0 RW |
200 | msgbuf_clear(&iev_main->ibuf.w); |
201 | close(iev_main->ibuf.fd); | |
50732983 | 202 | iev_main->ibuf.fd = -1; |
28e8294c RW |
203 | msgbuf_clear(&iev_main_sync->ibuf.w); |
204 | close(iev_main_sync->ibuf.fd); | |
50732983 | 205 | iev_main_sync->ibuf.fd = -1; |
8429abe0 | 206 | |
274f5abf | 207 | control_cleanup(ctl_sock_path); |
8429abe0 RW |
208 | config_clear(leconf); |
209 | ||
eac6e3f0 | 210 | #ifdef __OpenBSD__ |
8429abe0 | 211 | if (sysdep.no_pfkey == 0) { |
50478845 | 212 | thread_cancel(&pfkey_ev); |
8429abe0 RW |
213 | close(global.pfkeysock); |
214 | } | |
eac6e3f0 | 215 | #endif |
8429abe0 RW |
216 | ldpe_close_sockets(AF_INET); |
217 | ldpe_close_sockets(AF_INET6); | |
218 | ||
219 | /* remove addresses from global list */ | |
220 | while ((if_addr = LIST_FIRST(&global.addr_list)) != NULL) { | |
221 | LIST_REMOVE(if_addr, entry); | |
11bf8e13 | 222 | assert(if_addr != LIST_FIRST(&global.addr_list)); |
8429abe0 RW |
223 | free(if_addr); |
224 | } | |
55cd0f61 DS |
225 | while (!RB_EMPTY(global_adj_head, &global.adj_tree)) { |
226 | adj = RB_ROOT(global_adj_head, &global.adj_tree); | |
227 | ||
8429abe0 | 228 | adj_del(adj, S_SHUTDOWN); |
55cd0f61 | 229 | } |
8429abe0 RW |
230 | |
231 | /* clean up */ | |
835a7376 RW |
232 | if (iev_lde) |
233 | free(iev_lde); | |
8429abe0 RW |
234 | free(iev_main); |
235 | free(pkt_ptr); | |
236 | ||
237 | log_info("ldp engine exiting"); | |
b12a63f1 MS |
238 | |
239 | zlog_fini(); | |
240 | ||
8429abe0 RW |
241 | exit(0); |
242 | } | |
243 | ||
244 | /* imesg */ | |
245 | int | |
246 | ldpe_imsg_compose_parent(int type, pid_t pid, void *data, uint16_t datalen) | |
247 | { | |
50732983 RW |
248 | if (iev_main->ibuf.fd == -1) |
249 | return (0); | |
8429abe0 RW |
250 | return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen)); |
251 | } | |
252 | ||
f2232fdf RW |
253 | void |
254 | ldpe_imsg_compose_parent_sync(int type, pid_t pid, void *data, uint16_t datalen) | |
255 | { | |
50732983 RW |
256 | if (iev_main_sync->ibuf.fd == -1) |
257 | return; | |
f2232fdf RW |
258 | imsg_compose_event(iev_main_sync, type, 0, pid, -1, data, datalen); |
259 | imsg_flush(&iev_main_sync->ibuf); | |
260 | } | |
261 | ||
8429abe0 RW |
262 | int |
263 | ldpe_imsg_compose_lde(int type, uint32_t peerid, pid_t pid, void *data, | |
264 | uint16_t datalen) | |
265 | { | |
50732983 RW |
266 | if (iev_lde->ibuf.fd == -1) |
267 | return (0); | |
8429abe0 RW |
268 | return (imsg_compose_event(iev_lde, type, peerid, pid, -1, |
269 | data, datalen)); | |
270 | } | |
271 | ||
272 | /* ARGSUSED */ | |
eac6e3f0 RW |
273 | static int |
274 | ldpe_dispatch_main(struct thread *thread) | |
8429abe0 RW |
275 | { |
276 | static struct ldpd_conf *nconf; | |
277 | struct iface *niface; | |
278 | struct tnbr *ntnbr; | |
279 | struct nbr_params *nnbrp; | |
26519d8c | 280 | static struct l2vpn *l2vpn, *nl2vpn; |
52b530fc RW |
281 | struct l2vpn_if *lif, *nlif; |
282 | struct l2vpn_pw *pw, *npw; | |
8429abe0 | 283 | struct imsg imsg; |
11bf8e13 | 284 | int fd; |
eac6e3f0 | 285 | struct imsgev *iev = THREAD_ARG(thread); |
8429abe0 RW |
286 | struct imsgbuf *ibuf = &iev->ibuf; |
287 | struct iface *iface = NULL; | |
288 | struct kif *kif; | |
289 | int af; | |
290 | enum socket_type *socket_type; | |
291 | static int disc_socket = -1; | |
292 | static int edisc_socket = -1; | |
293 | static int session_socket = -1; | |
294 | struct nbr *nbr; | |
eac6e3f0 | 295 | #ifdef __OpenBSD__ |
8429abe0 | 296 | struct nbr_params *nbrp; |
eac6e3f0 | 297 | #endif |
8429abe0 | 298 | int n, shut = 0; |
2d1aa1e8 | 299 | struct ldp_access *laccess; |
e1894ff7 | 300 | struct ldp_igp_sync_if_state_req *ldp_sync_if_state_req; |
2d1aa1e8 | 301 | |
eac6e3f0 RW |
302 | iev->ev_read = NULL; |
303 | ||
304 | if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) | |
305 | fatal("imsg_read error"); | |
306 | if (n == 0) /* connection closed */ | |
307 | shut = 1; | |
8429abe0 RW |
308 | |
309 | for (;;) { | |
310 | if ((n = imsg_get(ibuf, &imsg)) == -1) | |
311 | fatal("ldpe_dispatch_main: imsg_get error"); | |
312 | if (n == 0) | |
313 | break; | |
314 | ||
315 | switch (imsg.hdr.type) { | |
316 | case IMSG_IFSTATUS: | |
317 | if (imsg.hdr.len != IMSG_HEADER_SIZE + | |
318 | sizeof(struct kif)) | |
319 | fatalx("IFSTATUS imsg with wrong len"); | |
320 | kif = imsg.data; | |
321 | ||
eac6e3f0 | 322 | iface = if_lookup_name(leconf, kif->ifname); |
26519d8c RW |
323 | if (iface) { |
324 | if_update_info(iface, kif); | |
61cd1100 | 325 | ldp_if_update(iface, AF_UNSPEC); |
8429abe0 | 326 | break; |
26519d8c | 327 | } |
8429abe0 | 328 | |
26519d8c | 329 | RB_FOREACH(l2vpn, l2vpn_head, &leconf->l2vpn_tree) { |
52bd4c23 | 330 | lif = l2vpn_if_find(l2vpn, kif->ifname); |
26519d8c | 331 | if (lif) { |
52b530fc | 332 | l2vpn_if_update_info(lif, kif); |
26519d8c RW |
333 | l2vpn_if_update(lif); |
334 | break; | |
335 | } | |
52b530fc RW |
336 | pw = l2vpn_pw_find(l2vpn, kif->ifname); |
337 | if (pw) { | |
338 | l2vpn_pw_update_info(pw, kif); | |
339 | break; | |
340 | } | |
26519d8c | 341 | } |
8429abe0 RW |
342 | break; |
343 | case IMSG_NEWADDR: | |
344 | if (imsg.hdr.len != IMSG_HEADER_SIZE + | |
345 | sizeof(struct kaddr)) | |
346 | fatalx("NEWADDR imsg with wrong len"); | |
347 | ||
348 | if_addr_add(imsg.data); | |
349 | break; | |
350 | case IMSG_DELADDR: | |
351 | if (imsg.hdr.len != IMSG_HEADER_SIZE + | |
352 | sizeof(struct kaddr)) | |
353 | fatalx("DELADDR imsg with wrong len"); | |
354 | ||
355 | if_addr_del(imsg.data); | |
356 | break; | |
357 | case IMSG_SOCKET_IPC: | |
358 | if (iev_lde) { | |
3efd0893 | 359 | log_warnx("%s: received unexpected imsg fd to lde", __func__); |
8429abe0 RW |
360 | break; |
361 | } | |
362 | if ((fd = imsg.fd) == -1) { | |
3efd0893 | 363 | log_warnx("%s: expected to receive imsg fd to lde but didn't receive any", __func__); |
8429abe0 RW |
364 | break; |
365 | } | |
366 | ||
367 | if ((iev_lde = malloc(sizeof(struct imsgev))) == NULL) | |
368 | fatal(NULL); | |
369 | imsg_init(&iev_lde->ibuf, fd); | |
eac6e3f0 | 370 | iev_lde->handler_read = ldpe_dispatch_lde; |
66e78ae6 QY |
371 | iev_lde->ev_read = NULL; |
372 | thread_add_read(master, iev_lde->handler_read, iev_lde, iev_lde->ibuf.fd, | |
373 | &iev_lde->ev_read); | |
eac6e3f0 RW |
374 | iev_lde->handler_write = ldp_write_handler; |
375 | iev_lde->ev_write = NULL; | |
8429abe0 | 376 | break; |
274f5abf RW |
377 | case IMSG_INIT: |
378 | if (imsg.hdr.len != IMSG_HEADER_SIZE + | |
379 | sizeof(struct ldpd_init)) | |
380 | fatalx("INIT imsg with wrong len"); | |
381 | ||
382 | memcpy(&init, imsg.data, sizeof(init)); | |
383 | ldpe_init(&init); | |
384 | break; | |
8429abe0 RW |
385 | case IMSG_CLOSE_SOCKETS: |
386 | af = imsg.hdr.peerid; | |
387 | ||
388 | RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) { | |
389 | if (nbr->af != af) | |
390 | continue; | |
391 | session_shutdown(nbr, S_SHUTDOWN, 0, 0); | |
eac6e3f0 | 392 | #ifdef __OpenBSD__ |
8429abe0 | 393 | pfkey_remove(nbr); |
eac6e3f0 | 394 | #endif |
0f7b5df9 | 395 | nbr->auth.method = AUTH_NONE; |
8429abe0 RW |
396 | } |
397 | ldpe_close_sockets(af); | |
398 | if_update_all(af); | |
399 | tnbr_update_all(af); | |
400 | ||
401 | disc_socket = -1; | |
402 | edisc_socket = -1; | |
403 | session_socket = -1; | |
404 | if ((ldp_af_conf_get(leconf, af))->flags & | |
405 | F_LDPD_AF_ENABLED) | |
406 | ldpe_imsg_compose_parent(IMSG_REQUEST_SOCKETS, | |
407 | af, NULL, 0); | |
408 | break; | |
409 | case IMSG_SOCKET_NET: | |
410 | if (imsg.hdr.len != IMSG_HEADER_SIZE + | |
411 | sizeof(enum socket_type)) | |
412 | fatalx("SOCKET_NET imsg with wrong len"); | |
413 | socket_type = imsg.data; | |
414 | ||
415 | switch (*socket_type) { | |
416 | case LDP_SOCKET_DISC: | |
417 | disc_socket = imsg.fd; | |
418 | break; | |
419 | case LDP_SOCKET_EDISC: | |
420 | edisc_socket = imsg.fd; | |
421 | break; | |
422 | case LDP_SOCKET_SESSION: | |
423 | session_socket = imsg.fd; | |
424 | break; | |
425 | } | |
426 | break; | |
427 | case IMSG_SETUP_SOCKETS: | |
428 | af = imsg.hdr.peerid; | |
429 | if (disc_socket == -1 || edisc_socket == -1 || | |
430 | session_socket == -1) { | |
431 | if (disc_socket != -1) | |
432 | close(disc_socket); | |
433 | if (edisc_socket != -1) | |
434 | close(edisc_socket); | |
435 | if (session_socket != -1) | |
436 | close(session_socket); | |
437 | break; | |
438 | } | |
439 | ||
440 | ldpe_setup_sockets(af, disc_socket, edisc_socket, | |
441 | session_socket); | |
442 | if_update_all(af); | |
443 | tnbr_update_all(af); | |
444 | RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) { | |
445 | if (nbr->af != af) | |
446 | continue; | |
447 | nbr->laddr = (ldp_af_conf_get(leconf, | |
448 | af))->trans_addr; | |
eac6e3f0 | 449 | #ifdef __OpenBSD__ |
8429abe0 | 450 | nbrp = nbr_params_find(leconf, nbr->id); |
0f7b5df9 RW |
451 | if (nbrp) { |
452 | nbr->auth.method = nbrp->auth.method; | |
453 | if (pfkey_establish(nbr, nbrp) == -1) | |
454 | fatalx("pfkey setup failed"); | |
455 | } | |
eac6e3f0 | 456 | #endif |
8429abe0 RW |
457 | if (nbr_session_active_role(nbr)) |
458 | nbr_establish_connection(nbr); | |
459 | } | |
460 | break; | |
eac6e3f0 RW |
461 | case IMSG_RTRID_UPDATE: |
462 | memcpy(&global.rtr_id, imsg.data, | |
463 | sizeof(global.rtr_id)); | |
464 | if (leconf->rtr_id.s_addr == INADDR_ANY) { | |
45a8eba9 | 465 | ldpe_reset_nbrs(AF_UNSPEC); |
eac6e3f0 RW |
466 | } |
467 | if_update_all(AF_UNSPEC); | |
468 | tnbr_update_all(AF_UNSPEC); | |
469 | break; | |
8429abe0 RW |
470 | case IMSG_RECONF_CONF: |
471 | if ((nconf = malloc(sizeof(struct ldpd_conf))) == | |
472 | NULL) | |
473 | fatal(NULL); | |
474 | memcpy(nconf, imsg.data, sizeof(struct ldpd_conf)); | |
475 | ||
45926e58 RZ |
476 | RB_INIT(iface_head, &nconf->iface_tree); |
477 | RB_INIT(tnbr_head, &nconf->tnbr_tree); | |
478 | RB_INIT(nbrp_head, &nconf->nbrp_tree); | |
479 | RB_INIT(l2vpn_head, &nconf->l2vpn_tree); | |
8429abe0 RW |
480 | break; |
481 | case IMSG_RECONF_IFACE: | |
482 | if ((niface = malloc(sizeof(struct iface))) == NULL) | |
483 | fatal(NULL); | |
484 | memcpy(niface, imsg.data, sizeof(struct iface)); | |
485 | ||
7d3d7491 | 486 | RB_INSERT(iface_head, &nconf->iface_tree, niface); |
8429abe0 RW |
487 | break; |
488 | case IMSG_RECONF_TNBR: | |
489 | if ((ntnbr = malloc(sizeof(struct tnbr))) == NULL) | |
490 | fatal(NULL); | |
491 | memcpy(ntnbr, imsg.data, sizeof(struct tnbr)); | |
492 | ||
7989cdba | 493 | RB_INSERT(tnbr_head, &nconf->tnbr_tree, ntnbr); |
8429abe0 RW |
494 | break; |
495 | case IMSG_RECONF_NBRP: | |
496 | if ((nnbrp = malloc(sizeof(struct nbr_params))) == NULL) | |
497 | fatal(NULL); | |
498 | memcpy(nnbrp, imsg.data, sizeof(struct nbr_params)); | |
499 | ||
76c4abd1 | 500 | RB_INSERT(nbrp_head, &nconf->nbrp_tree, nnbrp); |
8429abe0 RW |
501 | break; |
502 | case IMSG_RECONF_L2VPN: | |
503 | if ((nl2vpn = malloc(sizeof(struct l2vpn))) == NULL) | |
504 | fatal(NULL); | |
505 | memcpy(nl2vpn, imsg.data, sizeof(struct l2vpn)); | |
506 | ||
45926e58 RZ |
507 | RB_INIT(l2vpn_if_head, &nl2vpn->if_tree); |
508 | RB_INIT(l2vpn_pw_head, &nl2vpn->pw_tree); | |
509 | RB_INIT(l2vpn_pw_head, &nl2vpn->pw_inactive_tree); | |
8429abe0 | 510 | |
90d7e7bd | 511 | RB_INSERT(l2vpn_head, &nconf->l2vpn_tree, nl2vpn); |
8429abe0 RW |
512 | break; |
513 | case IMSG_RECONF_L2VPN_IF: | |
514 | if ((nlif = malloc(sizeof(struct l2vpn_if))) == NULL) | |
515 | fatal(NULL); | |
516 | memcpy(nlif, imsg.data, sizeof(struct l2vpn_if)); | |
517 | ||
029c1958 | 518 | RB_INSERT(l2vpn_if_head, &nl2vpn->if_tree, nlif); |
8429abe0 RW |
519 | break; |
520 | case IMSG_RECONF_L2VPN_PW: | |
521 | if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL) | |
522 | fatal(NULL); | |
523 | memcpy(npw, imsg.data, sizeof(struct l2vpn_pw)); | |
524 | ||
20bacaeb | 525 | RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_tree, npw); |
8429abe0 | 526 | break; |
eac6e3f0 RW |
527 | case IMSG_RECONF_L2VPN_IPW: |
528 | if ((npw = malloc(sizeof(struct l2vpn_pw))) == NULL) | |
529 | fatal(NULL); | |
530 | memcpy(npw, imsg.data, sizeof(struct l2vpn_pw)); | |
531 | ||
20bacaeb | 532 | RB_INSERT(l2vpn_pw_head, &nl2vpn->pw_inactive_tree, npw); |
eac6e3f0 | 533 | break; |
8429abe0 RW |
534 | case IMSG_RECONF_END: |
535 | merge_config(leconf, nconf); | |
1d75a89d | 536 | ldp_clear_config(nconf); |
8429abe0 RW |
537 | nconf = NULL; |
538 | global.conf_seqnum++; | |
539 | break; | |
8429abe0 RW |
540 | case IMSG_CTL_END: |
541 | control_imsg_relay(&imsg); | |
542 | break; | |
eac6e3f0 RW |
543 | case IMSG_DEBUG_UPDATE: |
544 | if (imsg.hdr.len != IMSG_HEADER_SIZE + | |
545 | sizeof(ldp_debug)) { | |
546 | log_warnx("%s: wrong imsg len", __func__); | |
547 | break; | |
548 | } | |
549 | memcpy(&ldp_debug, imsg.data, sizeof(ldp_debug)); | |
550 | break; | |
2d1aa1e8 | 551 | case IMSG_FILTER_UPDATE: |
552 | if (imsg.hdr.len != IMSG_HEADER_SIZE + | |
553 | sizeof(struct ldp_access)) { | |
554 | log_warnx("%s: wrong imsg len", __func__); | |
555 | break; | |
556 | } | |
557 | laccess = imsg.data; | |
558 | ldpe_check_filter_af(AF_INET, &leconf->ipv4, | |
559 | laccess->name); | |
560 | ldpe_check_filter_af(AF_INET6, &leconf->ipv6, | |
561 | laccess->name); | |
562 | break; | |
e1894ff7 KS |
563 | case IMSG_LDP_SYNC_IF_STATE_REQUEST: |
564 | if (imsg.hdr.len != IMSG_HEADER_SIZE + | |
565 | sizeof(struct ldp_igp_sync_if_state_req)) { | |
566 | log_warnx("%s: wrong imsg len", __func__); | |
567 | break; | |
568 | } | |
569 | ldp_sync_if_state_req = imsg.data; | |
570 | ldp_sync_fsm_state_req(ldp_sync_if_state_req); | |
571 | break; | |
8429abe0 RW |
572 | default: |
573 | log_debug("ldpe_dispatch_main: error handling imsg %d", | |
574 | imsg.hdr.type); | |
575 | break; | |
576 | } | |
577 | imsg_free(&imsg); | |
578 | } | |
579 | if (!shut) | |
580 | imsg_event_add(iev); | |
581 | else { | |
eac6e3f0 | 582 | /* this pipe is dead, so remove the event handlers and exit */ |
50478845 MS |
583 | thread_cancel(&iev->ev_read); |
584 | thread_cancel(&iev->ev_write); | |
eac6e3f0 | 585 | ldpe_shutdown(); |
8429abe0 | 586 | } |
eac6e3f0 RW |
587 | |
588 | return (0); | |
8429abe0 RW |
589 | } |
590 | ||
591 | /* ARGSUSED */ | |
eac6e3f0 RW |
592 | static int |
593 | ldpe_dispatch_lde(struct thread *thread) | |
8429abe0 | 594 | { |
eac6e3f0 | 595 | struct imsgev *iev = THREAD_ARG(thread); |
8429abe0 RW |
596 | struct imsgbuf *ibuf = &iev->ibuf; |
597 | struct imsg imsg; | |
236c6935 RW |
598 | struct map *map; |
599 | struct notify_msg *nm; | |
600 | struct nbr *nbr; | |
8429abe0 | 601 | int n, shut = 0; |
8429abe0 | 602 | |
eac6e3f0 RW |
603 | iev->ev_read = NULL; |
604 | ||
605 | if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) | |
606 | fatal("imsg_read error"); | |
607 | if (n == 0) /* connection closed */ | |
608 | shut = 1; | |
8429abe0 RW |
609 | |
610 | for (;;) { | |
611 | if ((n = imsg_get(ibuf, &imsg)) == -1) | |
612 | fatal("ldpe_dispatch_lde: imsg_get error"); | |
613 | if (n == 0) | |
614 | break; | |
615 | ||
616 | switch (imsg.hdr.type) { | |
617 | case IMSG_MAPPING_ADD: | |
618 | case IMSG_RELEASE_ADD: | |
619 | case IMSG_REQUEST_ADD: | |
620 | case IMSG_WITHDRAW_ADD: | |
236c6935 RW |
621 | if (imsg.hdr.len - IMSG_HEADER_SIZE != |
622 | sizeof(struct map)) | |
8429abe0 | 623 | fatalx("invalid size of map request"); |
236c6935 | 624 | map = imsg.data; |
8429abe0 RW |
625 | |
626 | nbr = nbr_find_peerid(imsg.hdr.peerid); | |
95535717 | 627 | if (nbr == NULL) |
8429abe0 | 628 | break; |
8429abe0 RW |
629 | if (nbr->state != NBR_STA_OPER) |
630 | break; | |
631 | ||
632 | switch (imsg.hdr.type) { | |
633 | case IMSG_MAPPING_ADD: | |
236c6935 | 634 | mapping_list_add(&nbr->mapping_list, map); |
8429abe0 RW |
635 | break; |
636 | case IMSG_RELEASE_ADD: | |
236c6935 | 637 | mapping_list_add(&nbr->release_list, map); |
8429abe0 RW |
638 | break; |
639 | case IMSG_REQUEST_ADD: | |
236c6935 | 640 | mapping_list_add(&nbr->request_list, map); |
8429abe0 RW |
641 | break; |
642 | case IMSG_WITHDRAW_ADD: | |
236c6935 | 643 | mapping_list_add(&nbr->withdraw_list, map); |
8429abe0 RW |
644 | break; |
645 | } | |
646 | break; | |
647 | case IMSG_MAPPING_ADD_END: | |
648 | case IMSG_RELEASE_ADD_END: | |
649 | case IMSG_REQUEST_ADD_END: | |
650 | case IMSG_WITHDRAW_ADD_END: | |
651 | nbr = nbr_find_peerid(imsg.hdr.peerid); | |
95535717 | 652 | if (nbr == NULL) |
8429abe0 | 653 | break; |
8429abe0 RW |
654 | if (nbr->state != NBR_STA_OPER) |
655 | break; | |
656 | ||
657 | switch (imsg.hdr.type) { | |
658 | case IMSG_MAPPING_ADD_END: | |
659 | send_labelmessage(nbr, MSG_TYPE_LABELMAPPING, | |
660 | &nbr->mapping_list); | |
661 | break; | |
662 | case IMSG_RELEASE_ADD_END: | |
663 | send_labelmessage(nbr, MSG_TYPE_LABELRELEASE, | |
664 | &nbr->release_list); | |
665 | break; | |
666 | case IMSG_REQUEST_ADD_END: | |
667 | send_labelmessage(nbr, MSG_TYPE_LABELREQUEST, | |
668 | &nbr->request_list); | |
669 | break; | |
670 | case IMSG_WITHDRAW_ADD_END: | |
671 | send_labelmessage(nbr, MSG_TYPE_LABELWITHDRAW, | |
672 | &nbr->withdraw_list); | |
673 | break; | |
674 | } | |
675 | break; | |
676 | case IMSG_NOTIFICATION_SEND: | |
236c6935 RW |
677 | if (imsg.hdr.len - IMSG_HEADER_SIZE != |
678 | sizeof(struct notify_msg)) | |
8429abe0 | 679 | fatalx("invalid size of OE request"); |
236c6935 | 680 | nm = imsg.data; |
8429abe0 RW |
681 | |
682 | nbr = nbr_find_peerid(imsg.hdr.peerid); | |
683 | if (nbr == NULL) { | |
3efd0893 | 684 | log_debug("ldpe_dispatch_lde: cannot find neighbor"); |
8429abe0 RW |
685 | break; |
686 | } | |
687 | if (nbr->state != NBR_STA_OPER) | |
688 | break; | |
689 | ||
236c6935 | 690 | send_notification_full(nbr->tcp, nm); |
8429abe0 RW |
691 | break; |
692 | case IMSG_CTL_END: | |
0f7b5df9 RW |
693 | case IMSG_CTL_SHOW_LIB_BEGIN: |
694 | case IMSG_CTL_SHOW_LIB_RCVD: | |
695 | case IMSG_CTL_SHOW_LIB_SENT: | |
696 | case IMSG_CTL_SHOW_LIB_END: | |
8429abe0 RW |
697 | case IMSG_CTL_SHOW_L2VPN_PW: |
698 | case IMSG_CTL_SHOW_L2VPN_BINDING: | |
699 | control_imsg_relay(&imsg); | |
700 | break; | |
2d1aa1e8 | 701 | case IMSG_NBR_SHUTDOWN: |
702 | nbr = nbr_find_peerid(imsg.hdr.peerid); | |
703 | if (nbr == NULL) { | |
3efd0893 | 704 | log_debug("ldpe_dispatch_lde: cannot find neighbor"); |
2d1aa1e8 | 705 | break; |
706 | } | |
707 | if (nbr->state != NBR_STA_OPER) | |
708 | break; | |
709 | session_shutdown(nbr,S_SHUTDOWN,0,0); | |
710 | break; | |
8429abe0 RW |
711 | default: |
712 | log_debug("ldpe_dispatch_lde: error handling imsg %d", | |
713 | imsg.hdr.type); | |
714 | break; | |
715 | } | |
716 | imsg_free(&imsg); | |
717 | } | |
718 | if (!shut) | |
719 | imsg_event_add(iev); | |
720 | else { | |
eac6e3f0 | 721 | /* this pipe is dead, so remove the event handlers and exit */ |
50478845 MS |
722 | thread_cancel(&iev->ev_read); |
723 | thread_cancel(&iev->ev_write); | |
eac6e3f0 | 724 | ldpe_shutdown(); |
8429abe0 | 725 | } |
eac6e3f0 RW |
726 | |
727 | return (0); | |
8429abe0 RW |
728 | } |
729 | ||
eac6e3f0 | 730 | #ifdef __OpenBSD__ |
8429abe0 | 731 | /* ARGSUSED */ |
eac6e3f0 RW |
732 | static int |
733 | ldpe_dispatch_pfkey(struct thread *thread) | |
8429abe0 | 734 | { |
eac6e3f0 RW |
735 | int fd = THREAD_FD(thread); |
736 | ||
66e78ae6 QY |
737 | pfkey_ev = NULL; |
738 | thread_add_read(master, ldpe_dispatch_pfkey, NULL, global.pfkeysock, | |
739 | &pfkey_ev); | |
eac6e3f0 RW |
740 | |
741 | if (pfkey_read(fd, NULL) == -1) | |
742 | fatal("pfkey_read failed, exiting..."); | |
743 | ||
744 | return (0); | |
8429abe0 | 745 | } |
eac6e3f0 | 746 | #endif /* __OpenBSD__ */ |
8429abe0 RW |
747 | |
748 | static void | |
749 | ldpe_setup_sockets(int af, int disc_socket, int edisc_socket, | |
750 | int session_socket) | |
751 | { | |
752 | struct ldpd_af_global *af_global; | |
753 | ||
754 | af_global = ldp_af_global_get(&global, af); | |
755 | ||
756 | /* discovery socket */ | |
757 | af_global->ldp_disc_socket = disc_socket; | |
66e78ae6 QY |
758 | af_global->disc_ev = NULL; |
759 | thread_add_read(master, disc_recv_packet, &af_global->disc_ev, af_global->ldp_disc_socket, | |
760 | &af_global->disc_ev); | |
8429abe0 RW |
761 | |
762 | /* extended discovery socket */ | |
763 | af_global->ldp_edisc_socket = edisc_socket; | |
66e78ae6 QY |
764 | af_global->edisc_ev = NULL; |
765 | thread_add_read(master, disc_recv_packet, &af_global->edisc_ev, af_global->ldp_edisc_socket, | |
766 | &af_global->edisc_ev); | |
8429abe0 RW |
767 | |
768 | /* session socket */ | |
769 | af_global->ldp_session_socket = session_socket; | |
770 | accept_add(af_global->ldp_session_socket, session_accept, NULL); | |
771 | } | |
772 | ||
773 | static void | |
774 | ldpe_close_sockets(int af) | |
775 | { | |
776 | struct ldpd_af_global *af_global; | |
777 | ||
778 | af_global = ldp_af_global_get(&global, af); | |
779 | ||
780 | /* discovery socket */ | |
50478845 | 781 | thread_cancel(&af_global->disc_ev); |
8429abe0 RW |
782 | if (af_global->ldp_disc_socket != -1) { |
783 | close(af_global->ldp_disc_socket); | |
784 | af_global->ldp_disc_socket = -1; | |
785 | } | |
786 | ||
787 | /* extended discovery socket */ | |
50478845 | 788 | thread_cancel(&af_global->edisc_ev); |
8429abe0 RW |
789 | if (af_global->ldp_edisc_socket != -1) { |
790 | close(af_global->ldp_edisc_socket); | |
791 | af_global->ldp_edisc_socket = -1; | |
792 | } | |
793 | ||
794 | /* session socket */ | |
795 | if (af_global->ldp_session_socket != -1) { | |
796 | accept_del(af_global->ldp_session_socket); | |
797 | close(af_global->ldp_session_socket); | |
798 | af_global->ldp_session_socket = -1; | |
799 | } | |
800 | } | |
801 | ||
45a8eba9 RW |
802 | int |
803 | ldpe_acl_check(char *acl_name, int af, union ldpd_addr *addr, uint8_t prefixlen) | |
804 | { | |
805 | return ldp_acl_request(iev_main_sync, acl_name, af, addr, prefixlen); | |
806 | } | |
807 | ||
8429abe0 RW |
808 | void |
809 | ldpe_reset_nbrs(int af) | |
810 | { | |
811 | struct nbr *nbr; | |
812 | ||
813 | RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) { | |
45a8eba9 | 814 | if (af == AF_UNSPEC || nbr->af == af) |
8429abe0 RW |
815 | session_shutdown(nbr, S_SHUTDOWN, 0, 0); |
816 | } | |
817 | } | |
818 | ||
819 | void | |
820 | ldpe_reset_ds_nbrs(void) | |
821 | { | |
822 | struct nbr *nbr; | |
823 | ||
824 | RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) { | |
825 | if (nbr->ds_tlv) | |
826 | session_shutdown(nbr, S_SHUTDOWN, 0, 0); | |
827 | } | |
828 | } | |
829 | ||
830 | void | |
831 | ldpe_remove_dynamic_tnbrs(int af) | |
832 | { | |
833 | struct tnbr *tnbr, *safe; | |
834 | ||
7989cdba | 835 | RB_FOREACH_SAFE(tnbr, tnbr_head, &leconf->tnbr_tree, safe) { |
8429abe0 RW |
836 | if (tnbr->af != af) |
837 | continue; | |
838 | ||
839 | tnbr->flags &= ~F_TNBR_DYNAMIC; | |
7989cdba | 840 | tnbr_check(leconf, tnbr); |
8429abe0 RW |
841 | } |
842 | } | |
843 | ||
844 | void | |
845 | ldpe_stop_init_backoff(int af) | |
846 | { | |
847 | struct nbr *nbr; | |
848 | ||
849 | RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) { | |
850 | if (nbr->af == af && nbr_pending_idtimer(nbr)) { | |
851 | nbr_stop_idtimer(nbr); | |
852 | nbr_establish_connection(nbr); | |
853 | } | |
854 | } | |
855 | } | |
856 | ||
857 | static void | |
6cd8093d | 858 | ldpe_iface_af_ctl(struct ctl_conn *c, int af, ifindex_t idx) |
8429abe0 RW |
859 | { |
860 | struct iface *iface; | |
861 | struct iface_af *ia; | |
862 | struct ctl_iface *ictl; | |
863 | ||
7d3d7491 | 864 | RB_FOREACH(iface, iface_head, &leconf->iface_tree) { |
8429abe0 RW |
865 | if (idx == 0 || idx == iface->ifindex) { |
866 | ia = iface_af_get(iface, af); | |
867 | if (!ia->enabled) | |
868 | continue; | |
869 | ||
870 | ictl = if_to_ctl(ia); | |
05aac414 | 871 | imsg_compose_event(&c->iev, IMSG_CTL_SHOW_INTERFACE, |
8429abe0 RW |
872 | 0, 0, -1, ictl, sizeof(struct ctl_iface)); |
873 | } | |
874 | } | |
875 | } | |
876 | ||
877 | void | |
6cd8093d | 878 | ldpe_iface_ctl(struct ctl_conn *c, ifindex_t idx) |
8429abe0 RW |
879 | { |
880 | ldpe_iface_af_ctl(c, AF_INET, idx); | |
881 | ldpe_iface_af_ctl(c, AF_INET6, idx); | |
882 | } | |
883 | ||
884 | void | |
885 | ldpe_adj_ctl(struct ctl_conn *c) | |
bc0eb287 RW |
886 | { |
887 | struct adj *adj; | |
888 | struct ctl_adj *actl; | |
889 | ||
890 | RB_FOREACH(adj, global_adj_head, &global.adj_tree) { | |
891 | actl = adj_to_ctl(adj); | |
892 | imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISCOVERY, 0, 0, | |
893 | -1, actl, sizeof(struct ctl_adj)); | |
894 | } | |
895 | ||
896 | imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0); | |
897 | } | |
898 | ||
899 | void | |
900 | ldpe_adj_detail_ctl(struct ctl_conn *c) | |
8429abe0 | 901 | { |
eac6e3f0 RW |
902 | struct iface *iface; |
903 | struct tnbr *tnbr; | |
904 | struct adj *adj; | |
905 | struct ctl_adj *actl; | |
906 | struct ctl_disc_if ictl; | |
907 | struct ctl_disc_tnbr tctl; | |
8429abe0 | 908 | |
eac6e3f0 RW |
909 | imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISCOVERY, 0, 0, -1, NULL, 0); |
910 | ||
7d3d7491 | 911 | RB_FOREACH(iface, iface_head, &leconf->iface_tree) { |
eac6e3f0 RW |
912 | memset(&ictl, 0, sizeof(ictl)); |
913 | ictl.active_v4 = (iface->ipv4.state == IF_STA_ACTIVE); | |
914 | ictl.active_v6 = (iface->ipv6.state == IF_STA_ACTIVE); | |
915 | ||
916 | if (!ictl.active_v4 && !ictl.active_v6) | |
917 | continue; | |
918 | ||
919 | strlcpy(ictl.name, iface->name, sizeof(ictl.name)); | |
45926e58 RZ |
920 | if (RB_EMPTY(ia_adj_head, &iface->ipv4.adj_tree) && |
921 | RB_EMPTY(ia_adj_head, &iface->ipv6.adj_tree)) | |
eac6e3f0 RW |
922 | ictl.no_adj = 1; |
923 | imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_IFACE, 0, 0, | |
924 | -1, &ictl, sizeof(ictl)); | |
925 | ||
057d48bd | 926 | RB_FOREACH(adj, ia_adj_head, &iface->ipv4.adj_tree) { |
8429abe0 | 927 | actl = adj_to_ctl(adj); |
eac6e3f0 RW |
928 | imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_ADJ, |
929 | 0, 0, -1, actl, sizeof(struct ctl_adj)); | |
930 | } | |
057d48bd | 931 | RB_FOREACH(adj, ia_adj_head, &iface->ipv6.adj_tree) { |
eac6e3f0 RW |
932 | actl = adj_to_ctl(adj); |
933 | imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_ADJ, | |
8429abe0 RW |
934 | 0, 0, -1, actl, sizeof(struct ctl_adj)); |
935 | } | |
936 | } | |
eac6e3f0 | 937 | |
7989cdba | 938 | RB_FOREACH(tnbr, tnbr_head, &leconf->tnbr_tree) { |
eac6e3f0 RW |
939 | memset(&tctl, 0, sizeof(tctl)); |
940 | tctl.af = tnbr->af; | |
941 | tctl.addr = tnbr->addr; | |
942 | if (tnbr->adj == NULL) | |
943 | tctl.no_adj = 1; | |
944 | ||
945 | imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_TNBR, 0, 0, | |
946 | -1, &tctl, sizeof(tctl)); | |
947 | ||
948 | if (tnbr->adj == NULL) | |
8429abe0 RW |
949 | continue; |
950 | ||
eac6e3f0 RW |
951 | actl = adj_to_ctl(tnbr->adj); |
952 | imsg_compose_event(&c->iev, IMSG_CTL_SHOW_DISC_ADJ, 0, 0, | |
8429abe0 RW |
953 | -1, actl, sizeof(struct ctl_adj)); |
954 | } | |
955 | ||
956 | imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0); | |
957 | } | |
958 | ||
959 | void | |
960 | ldpe_nbr_ctl(struct ctl_conn *c) | |
961 | { | |
eac6e3f0 RW |
962 | struct adj *adj; |
963 | struct ctl_adj *actl; | |
8429abe0 RW |
964 | struct nbr *nbr; |
965 | struct ctl_nbr *nctl; | |
966 | ||
967 | RB_FOREACH(nbr, nbr_addr_head, &nbrs_by_addr) { | |
eac6e3f0 RW |
968 | if (nbr->state == NBR_STA_PRESENT) |
969 | continue; | |
970 | ||
8429abe0 RW |
971 | nctl = nbr_to_ctl(nbr); |
972 | imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR, 0, 0, -1, nctl, | |
973 | sizeof(struct ctl_nbr)); | |
eac6e3f0 | 974 | |
057d48bd | 975 | RB_FOREACH(adj, nbr_adj_head, &nbr->adj_tree) { |
eac6e3f0 RW |
976 | actl = adj_to_ctl(adj); |
977 | imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR_DISC, | |
978 | 0, 0, -1, actl, sizeof(struct ctl_adj)); | |
979 | } | |
980 | ||
981 | imsg_compose_event(&c->iev, IMSG_CTL_SHOW_NBR_END, 0, 0, -1, | |
982 | NULL, 0); | |
8429abe0 RW |
983 | } |
984 | imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0); | |
985 | } | |
986 | ||
e1894ff7 KS |
987 | void |
988 | ldpe_ldp_sync_ctl(struct ctl_conn *c) | |
989 | { | |
990 | struct iface *iface; | |
991 | struct ctl_ldp_sync *ictl; | |
992 | ||
993 | RB_FOREACH(iface, iface_head, &leconf->iface_tree) { | |
994 | ictl = ldp_sync_to_ctl(iface); | |
995 | imsg_compose_event(&c->iev, IMSG_CTL_SHOW_LDP_SYNC, | |
996 | 0, 0, -1, ictl, sizeof(struct ctl_ldp_sync)); | |
997 | } | |
998 | imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0); | |
999 | } | |
1000 | ||
8429abe0 RW |
1001 | void |
1002 | mapping_list_add(struct mapping_head *mh, struct map *map) | |
1003 | { | |
1004 | struct mapping_entry *me; | |
1005 | ||
1006 | me = calloc(1, sizeof(*me)); | |
1007 | if (me == NULL) | |
1008 | fatal(__func__); | |
1009 | me->map = *map; | |
1010 | ||
1011 | TAILQ_INSERT_TAIL(mh, me, entry); | |
1012 | } | |
1013 | ||
1014 | void | |
1015 | mapping_list_clr(struct mapping_head *mh) | |
1016 | { | |
1017 | struct mapping_entry *me; | |
1018 | ||
1019 | while ((me = TAILQ_FIRST(mh)) != NULL) { | |
1020 | TAILQ_REMOVE(mh, me, entry); | |
11bf8e13 | 1021 | assert(me != TAILQ_FIRST(mh)); |
8429abe0 RW |
1022 | free(me); |
1023 | } | |
1024 | } | |
2d1aa1e8 | 1025 | |
1026 | void | |
1027 | ldpe_check_filter_af(int af, struct ldpd_af_conf *af_conf, | |
1028 | const char *filter_name) | |
1029 | { | |
1030 | if (strcmp(af_conf->acl_thello_accept_from, filter_name) == 0) | |
1031 | ldpe_remove_dynamic_tnbrs(af); | |
1032 | } |