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