1 |
|
|
/* $OpenBSD: ldpd.c,v 1.62 2017/03/03 23:36:06 renato 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 <sys/wait.h> |
24 |
|
|
#include <err.h> |
25 |
|
|
#include <errno.h> |
26 |
|
|
#include <pwd.h> |
27 |
|
|
#include <stdio.h> |
28 |
|
|
#include <stdlib.h> |
29 |
|
|
#include <string.h> |
30 |
|
|
#include <signal.h> |
31 |
|
|
#include <unistd.h> |
32 |
|
|
|
33 |
|
|
#include "ldpd.h" |
34 |
|
|
#include "ldpe.h" |
35 |
|
|
#include "lde.h" |
36 |
|
|
#include "log.h" |
37 |
|
|
|
38 |
|
|
static void main_sig_handler(int, short, void *); |
39 |
|
|
static __dead void usage(void); |
40 |
|
|
static __dead void ldpd_shutdown(void); |
41 |
|
|
static pid_t start_child(enum ldpd_process, char *, int, int, int, |
42 |
|
|
char *); |
43 |
|
|
static void main_dispatch_ldpe(int, short, void *); |
44 |
|
|
static void main_dispatch_lde(int, short, void *); |
45 |
|
|
static int main_imsg_compose_both(enum imsg_type, void *, |
46 |
|
|
uint16_t); |
47 |
|
|
static int main_imsg_send_ipc_sockets(struct imsgbuf *, |
48 |
|
|
struct imsgbuf *); |
49 |
|
|
static void main_imsg_send_net_sockets(int); |
50 |
|
|
static void main_imsg_send_net_socket(int, enum socket_type); |
51 |
|
|
static int main_imsg_send_config(struct ldpd_conf *); |
52 |
|
|
static int ldp_reload(void); |
53 |
|
|
static void merge_global(struct ldpd_conf *, struct ldpd_conf *); |
54 |
|
|
static void merge_af(int, struct ldpd_af_conf *, |
55 |
|
|
struct ldpd_af_conf *); |
56 |
|
|
static void merge_ifaces(struct ldpd_conf *, struct ldpd_conf *); |
57 |
|
|
static void merge_iface_af(struct iface_af *, struct iface_af *); |
58 |
|
|
static void merge_tnbrs(struct ldpd_conf *, struct ldpd_conf *); |
59 |
|
|
static void merge_nbrps(struct ldpd_conf *, struct ldpd_conf *); |
60 |
|
|
static void merge_l2vpns(struct ldpd_conf *, struct ldpd_conf *); |
61 |
|
|
static void merge_l2vpn(struct ldpd_conf *, struct l2vpn *, |
62 |
|
|
struct l2vpn *); |
63 |
|
|
|
64 |
|
|
struct ldpd_global global; |
65 |
|
|
struct ldpd_conf *ldpd_conf; |
66 |
|
|
|
67 |
|
|
static char *conffile; |
68 |
|
|
static struct imsgev *iev_ldpe; |
69 |
|
|
static struct imsgev *iev_lde; |
70 |
|
|
static pid_t ldpe_pid; |
71 |
|
|
static pid_t lde_pid; |
72 |
|
|
|
73 |
|
|
/* ARGSUSED */ |
74 |
|
|
static void |
75 |
|
|
main_sig_handler(int sig, short event, void *arg) |
76 |
|
|
{ |
77 |
|
|
/* signal handler rules don't apply, libevent decouples for us */ |
78 |
|
|
switch (sig) { |
79 |
|
|
case SIGTERM: |
80 |
|
|
case SIGINT: |
81 |
|
|
ldpd_shutdown(); |
82 |
|
|
/* NOTREACHED */ |
83 |
|
|
case SIGHUP: |
84 |
|
|
if (ldp_reload() == -1) |
85 |
|
|
log_warnx("configuration reload failed"); |
86 |
|
|
else |
87 |
|
|
log_debug("configuration reloaded"); |
88 |
|
|
break; |
89 |
|
|
default: |
90 |
|
|
fatalx("unexpected signal"); |
91 |
|
|
/* NOTREACHED */ |
92 |
|
|
} |
93 |
|
|
} |
94 |
|
|
|
95 |
|
|
static __dead void |
96 |
|
|
usage(void) |
97 |
|
|
{ |
98 |
|
|
extern char *__progname; |
99 |
|
|
|
100 |
|
|
fprintf(stderr, "usage: %s [-dnv] [-D macro=value] [-f file]" |
101 |
|
|
" [-s socket]\n", __progname); |
102 |
|
|
exit(1); |
103 |
|
|
} |
104 |
|
|
|
105 |
|
|
int |
106 |
|
|
main(int argc, char *argv[]) |
107 |
|
|
{ |
108 |
|
|
struct event ev_sigint, ev_sigterm, ev_sighup; |
109 |
|
|
char *saved_argv0; |
110 |
|
|
int ch; |
111 |
|
|
int debug = 0, lflag = 0, eflag = 0; |
112 |
|
|
char *sockname; |
113 |
|
|
int pipe_parent2ldpe[2]; |
114 |
|
|
int pipe_parent2lde[2]; |
115 |
|
|
|
116 |
|
|
conffile = CONF_FILE; |
117 |
|
|
ldpd_process = PROC_MAIN; |
118 |
|
|
log_procname = log_procnames[ldpd_process]; |
119 |
|
|
sockname = LDPD_SOCKET; |
120 |
|
|
|
121 |
|
|
log_init(1); /* log to stderr until daemonized */ |
122 |
|
|
log_verbose(1); |
123 |
|
|
|
124 |
|
|
saved_argv0 = argv[0]; |
125 |
|
|
if (saved_argv0 == NULL) |
126 |
|
|
saved_argv0 = "ldpd"; |
127 |
|
|
|
128 |
|
|
while ((ch = getopt(argc, argv, "dD:f:ns:vLE")) != -1) { |
129 |
|
|
switch (ch) { |
130 |
|
|
case 'd': |
131 |
|
|
debug = 1; |
132 |
|
|
break; |
133 |
|
|
case 'D': |
134 |
|
|
if (cmdline_symset(optarg) < 0) |
135 |
|
|
log_warnx("could not parse macro definition %s", |
136 |
|
|
optarg); |
137 |
|
|
break; |
138 |
|
|
case 'f': |
139 |
|
|
conffile = optarg; |
140 |
|
|
break; |
141 |
|
|
case 'n': |
142 |
|
|
global.cmd_opts |= LDPD_OPT_NOACTION; |
143 |
|
|
break; |
144 |
|
|
case 's': |
145 |
|
|
sockname = optarg; |
146 |
|
|
break; |
147 |
|
|
case 'v': |
148 |
|
|
if (global.cmd_opts & LDPD_OPT_VERBOSE) |
149 |
|
|
global.cmd_opts |= LDPD_OPT_VERBOSE2; |
150 |
|
|
global.cmd_opts |= LDPD_OPT_VERBOSE; |
151 |
|
|
break; |
152 |
|
|
case 'L': |
153 |
|
|
lflag = 1; |
154 |
|
|
break; |
155 |
|
|
case 'E': |
156 |
|
|
eflag = 1; |
157 |
|
|
break; |
158 |
|
|
default: |
159 |
|
|
usage(); |
160 |
|
|
/* NOTREACHED */ |
161 |
|
|
} |
162 |
|
|
} |
163 |
|
|
|
164 |
|
|
argc -= optind; |
165 |
|
|
argv += optind; |
166 |
|
|
if (argc > 0 || (lflag && eflag)) |
167 |
|
|
usage(); |
168 |
|
|
|
169 |
|
|
if (lflag) |
170 |
|
|
lde(debug, global.cmd_opts & LDPD_OPT_VERBOSE); |
171 |
|
|
else if (eflag) |
172 |
|
|
ldpe(debug, global.cmd_opts & LDPD_OPT_VERBOSE, sockname); |
173 |
|
|
|
174 |
|
|
/* fetch interfaces early */ |
175 |
|
|
kif_init(); |
176 |
|
|
|
177 |
|
|
/* parse config file */ |
178 |
|
|
if ((ldpd_conf = parse_config(conffile)) == NULL ) { |
179 |
|
|
kif_clear(); |
180 |
|
|
exit(1); |
181 |
|
|
} |
182 |
|
|
|
183 |
|
|
if (global.cmd_opts & LDPD_OPT_NOACTION) { |
184 |
|
|
if (global.cmd_opts & LDPD_OPT_VERBOSE) |
185 |
|
|
print_config(ldpd_conf); |
186 |
|
|
else |
187 |
|
|
fprintf(stderr, "configuration OK\n"); |
188 |
|
|
kif_clear(); |
189 |
|
|
exit(0); |
190 |
|
|
} |
191 |
|
|
|
192 |
|
|
/* check for root privileges */ |
193 |
|
|
if (geteuid()) |
194 |
|
|
errx(1, "need root privileges"); |
195 |
|
|
|
196 |
|
|
/* check for ldpd user */ |
197 |
|
|
if (getpwnam(LDPD_USER) == NULL) |
198 |
|
|
errx(1, "unknown user %s", LDPD_USER); |
199 |
|
|
|
200 |
|
|
log_init(debug); |
201 |
|
|
log_verbose(global.cmd_opts & (LDPD_OPT_VERBOSE | LDPD_OPT_VERBOSE2)); |
202 |
|
|
|
203 |
|
|
if (!debug) |
204 |
|
|
daemon(1, 0); |
205 |
|
|
|
206 |
|
|
log_info("startup"); |
207 |
|
|
|
208 |
|
|
if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, |
209 |
|
|
PF_UNSPEC, pipe_parent2ldpe) == -1) |
210 |
|
|
fatal("socketpair"); |
211 |
|
|
if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, |
212 |
|
|
PF_UNSPEC, pipe_parent2lde) == -1) |
213 |
|
|
fatal("socketpair"); |
214 |
|
|
|
215 |
|
|
/* start children */ |
216 |
|
|
lde_pid = start_child(PROC_LDE_ENGINE, saved_argv0, |
217 |
|
|
pipe_parent2lde[1], debug, global.cmd_opts & LDPD_OPT_VERBOSE, |
218 |
|
|
NULL); |
219 |
|
|
ldpe_pid = start_child(PROC_LDP_ENGINE, saved_argv0, |
220 |
|
|
pipe_parent2ldpe[1], debug, global.cmd_opts & LDPD_OPT_VERBOSE, |
221 |
|
|
sockname); |
222 |
|
|
|
223 |
|
|
event_init(); |
224 |
|
|
|
225 |
|
|
/* setup signal handler */ |
226 |
|
|
signal_set(&ev_sigint, SIGINT, main_sig_handler, NULL); |
227 |
|
|
signal_set(&ev_sigterm, SIGTERM, main_sig_handler, NULL); |
228 |
|
|
signal_set(&ev_sighup, SIGHUP, main_sig_handler, NULL); |
229 |
|
|
signal_add(&ev_sigint, NULL); |
230 |
|
|
signal_add(&ev_sigterm, NULL); |
231 |
|
|
signal_add(&ev_sighup, NULL); |
232 |
|
|
signal(SIGPIPE, SIG_IGN); |
233 |
|
|
|
234 |
|
|
/* setup pipes to children */ |
235 |
|
|
if ((iev_ldpe = malloc(sizeof(struct imsgev))) == NULL || |
236 |
|
|
(iev_lde = malloc(sizeof(struct imsgev))) == NULL) |
237 |
|
|
fatal(NULL); |
238 |
|
|
imsg_init(&iev_ldpe->ibuf, pipe_parent2ldpe[0]); |
239 |
|
|
iev_ldpe->handler = main_dispatch_ldpe; |
240 |
|
|
imsg_init(&iev_lde->ibuf, pipe_parent2lde[0]); |
241 |
|
|
iev_lde->handler = main_dispatch_lde; |
242 |
|
|
|
243 |
|
|
/* setup event handler */ |
244 |
|
|
iev_ldpe->events = EV_READ; |
245 |
|
|
event_set(&iev_ldpe->ev, iev_ldpe->ibuf.fd, iev_ldpe->events, |
246 |
|
|
iev_ldpe->handler, iev_ldpe); |
247 |
|
|
event_add(&iev_ldpe->ev, NULL); |
248 |
|
|
|
249 |
|
|
iev_lde->events = EV_READ; |
250 |
|
|
event_set(&iev_lde->ev, iev_lde->ibuf.fd, iev_lde->events, |
251 |
|
|
iev_lde->handler, iev_lde); |
252 |
|
|
event_add(&iev_lde->ev, NULL); |
253 |
|
|
|
254 |
|
|
if (main_imsg_send_ipc_sockets(&iev_ldpe->ibuf, &iev_lde->ibuf)) |
255 |
|
|
fatal("could not establish imsg links"); |
256 |
|
|
main_imsg_send_config(ldpd_conf); |
257 |
|
|
|
258 |
|
|
if (kr_init(!(ldpd_conf->flags & F_LDPD_NO_FIB_UPDATE), |
259 |
|
|
ldpd_conf->rdomain) == -1) |
260 |
|
|
fatalx("kr_init failed"); |
261 |
|
|
|
262 |
|
|
/* notify ldpe about existing interfaces and addresses */ |
263 |
|
|
kif_redistribute(NULL); |
264 |
|
|
|
265 |
|
|
if (ldpd_conf->ipv4.flags & F_LDPD_AF_ENABLED) |
266 |
|
|
main_imsg_send_net_sockets(AF_INET); |
267 |
|
|
if (ldpd_conf->ipv6.flags & F_LDPD_AF_ENABLED) |
268 |
|
|
main_imsg_send_net_sockets(AF_INET6); |
269 |
|
|
|
270 |
|
|
/* remove unneeded stuff from config */ |
271 |
|
|
/* ... */ |
272 |
|
|
|
273 |
|
|
event_dispatch(); |
274 |
|
|
|
275 |
|
|
ldpd_shutdown(); |
276 |
|
|
/* NOTREACHED */ |
277 |
|
|
return (0); |
278 |
|
|
} |
279 |
|
|
|
280 |
|
|
static __dead void |
281 |
|
|
ldpd_shutdown(void) |
282 |
|
|
{ |
283 |
|
|
pid_t pid; |
284 |
|
|
int status; |
285 |
|
|
|
286 |
|
|
/* close pipes */ |
287 |
|
|
msgbuf_clear(&iev_ldpe->ibuf.w); |
288 |
|
|
close(iev_ldpe->ibuf.fd); |
289 |
|
|
msgbuf_clear(&iev_lde->ibuf.w); |
290 |
|
|
close(iev_lde->ibuf.fd); |
291 |
|
|
|
292 |
|
|
kr_shutdown(); |
293 |
|
|
config_clear(ldpd_conf); |
294 |
|
|
|
295 |
|
|
log_debug("waiting for children to terminate"); |
296 |
|
|
do { |
297 |
|
|
pid = wait(&status); |
298 |
|
|
if (pid == -1) { |
299 |
|
|
if (errno != EINTR && errno != ECHILD) |
300 |
|
|
fatal("wait"); |
301 |
|
|
} else if (WIFSIGNALED(status)) |
302 |
|
|
log_warnx("%s terminated; signal %d", |
303 |
|
|
(pid == lde_pid) ? "label decision engine" : |
304 |
|
|
"ldp engine", WTERMSIG(status)); |
305 |
|
|
} while (pid != -1 || (pid == -1 && errno == EINTR)); |
306 |
|
|
|
307 |
|
|
free(iev_ldpe); |
308 |
|
|
free(iev_lde); |
309 |
|
|
|
310 |
|
|
log_info("terminating"); |
311 |
|
|
exit(0); |
312 |
|
|
} |
313 |
|
|
|
314 |
|
|
static pid_t |
315 |
|
|
start_child(enum ldpd_process p, char *argv0, int fd, int debug, int verbose, |
316 |
|
|
char *sockname) |
317 |
|
|
{ |
318 |
|
|
char *argv[5]; |
319 |
|
|
int argc = 0; |
320 |
|
|
pid_t pid; |
321 |
|
|
|
322 |
|
|
switch (pid = fork()) { |
323 |
|
|
case -1: |
324 |
|
|
fatal("cannot fork"); |
325 |
|
|
case 0: |
326 |
|
|
break; |
327 |
|
|
default: |
328 |
|
|
close(fd); |
329 |
|
|
return (pid); |
330 |
|
|
} |
331 |
|
|
|
332 |
|
|
if (dup2(fd, 3) == -1) |
333 |
|
|
fatal("cannot setup imsg fd"); |
334 |
|
|
|
335 |
|
|
argv[argc++] = argv0; |
336 |
|
|
switch (p) { |
337 |
|
|
case PROC_MAIN: |
338 |
|
|
fatalx("Can not start main process"); |
339 |
|
|
case PROC_LDE_ENGINE: |
340 |
|
|
argv[argc++] = "-L"; |
341 |
|
|
break; |
342 |
|
|
case PROC_LDP_ENGINE: |
343 |
|
|
argv[argc++] = "-E"; |
344 |
|
|
break; |
345 |
|
|
} |
346 |
|
|
if (debug) |
347 |
|
|
argv[argc++] = "-d"; |
348 |
|
|
if (verbose) |
349 |
|
|
argv[argc++] = "-v"; |
350 |
|
|
if (sockname) { |
351 |
|
|
argv[argc++] = "-s"; |
352 |
|
|
argv[argc++] = sockname; |
353 |
|
|
} |
354 |
|
|
argv[argc++] = NULL; |
355 |
|
|
|
356 |
|
|
execvp(argv0, argv); |
357 |
|
|
fatal("execvp"); |
358 |
|
|
} |
359 |
|
|
|
360 |
|
|
/* imsg handling */ |
361 |
|
|
/* ARGSUSED */ |
362 |
|
|
static void |
363 |
|
|
main_dispatch_ldpe(int fd, short event, void *bula) |
364 |
|
|
{ |
365 |
|
|
struct imsgev *iev = bula; |
366 |
|
|
struct imsgbuf *ibuf = &iev->ibuf; |
367 |
|
|
struct imsg imsg; |
368 |
|
|
int af; |
369 |
|
|
ssize_t n; |
370 |
|
|
int shut = 0, verbose; |
371 |
|
|
|
372 |
|
|
if (event & EV_READ) { |
373 |
|
|
if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) |
374 |
|
|
fatal("imsg_read error"); |
375 |
|
|
if (n == 0) /* connection closed */ |
376 |
|
|
shut = 1; |
377 |
|
|
} |
378 |
|
|
if (event & EV_WRITE) { |
379 |
|
|
if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) |
380 |
|
|
fatal("msgbuf_write"); |
381 |
|
|
if (n == 0) |
382 |
|
|
shut = 1; |
383 |
|
|
} |
384 |
|
|
|
385 |
|
|
for (;;) { |
386 |
|
|
if ((n = imsg_get(ibuf, &imsg)) == -1) |
387 |
|
|
fatal("imsg_get"); |
388 |
|
|
|
389 |
|
|
if (n == 0) |
390 |
|
|
break; |
391 |
|
|
|
392 |
|
|
switch (imsg.hdr.type) { |
393 |
|
|
case IMSG_REQUEST_SOCKETS: |
394 |
|
|
af = imsg.hdr.pid; |
395 |
|
|
main_imsg_send_net_sockets(af); |
396 |
|
|
break; |
397 |
|
|
case IMSG_CTL_RELOAD: |
398 |
|
|
if (ldp_reload() == -1) |
399 |
|
|
log_warnx("configuration reload failed"); |
400 |
|
|
else |
401 |
|
|
log_debug("configuration reloaded"); |
402 |
|
|
break; |
403 |
|
|
case IMSG_CTL_FIB_COUPLE: |
404 |
|
|
kr_fib_couple(); |
405 |
|
|
break; |
406 |
|
|
case IMSG_CTL_FIB_DECOUPLE: |
407 |
|
|
kr_fib_decouple(); |
408 |
|
|
break; |
409 |
|
|
case IMSG_CTL_KROUTE: |
410 |
|
|
case IMSG_CTL_KROUTE_ADDR: |
411 |
|
|
kr_show_route(&imsg); |
412 |
|
|
break; |
413 |
|
|
case IMSG_CTL_IFINFO: |
414 |
|
|
if (imsg.hdr.len == IMSG_HEADER_SIZE) |
415 |
|
|
kr_ifinfo(NULL, imsg.hdr.pid); |
416 |
|
|
else if (imsg.hdr.len == IMSG_HEADER_SIZE + IFNAMSIZ) |
417 |
|
|
kr_ifinfo(imsg.data, imsg.hdr.pid); |
418 |
|
|
else |
419 |
|
|
log_warnx("IFINFO request with wrong len"); |
420 |
|
|
break; |
421 |
|
|
case IMSG_CTL_LOG_VERBOSE: |
422 |
|
|
/* already checked by ldpe */ |
423 |
|
|
memcpy(&verbose, imsg.data, sizeof(verbose)); |
424 |
|
|
log_verbose(verbose); |
425 |
|
|
break; |
426 |
|
|
default: |
427 |
|
|
log_debug("%s: error handling imsg %d", __func__, |
428 |
|
|
imsg.hdr.type); |
429 |
|
|
break; |
430 |
|
|
} |
431 |
|
|
imsg_free(&imsg); |
432 |
|
|
} |
433 |
|
|
if (!shut) |
434 |
|
|
imsg_event_add(iev); |
435 |
|
|
else { |
436 |
|
|
/* this pipe is dead, so remove the event handler */ |
437 |
|
|
event_del(&iev->ev); |
438 |
|
|
event_loopexit(NULL); |
439 |
|
|
} |
440 |
|
|
} |
441 |
|
|
|
442 |
|
|
/* ARGSUSED */ |
443 |
|
|
static void |
444 |
|
|
main_dispatch_lde(int fd, short event, void *bula) |
445 |
|
|
{ |
446 |
|
|
struct imsgev *iev = bula; |
447 |
|
|
struct imsgbuf *ibuf = &iev->ibuf; |
448 |
|
|
struct imsg imsg; |
449 |
|
|
ssize_t n; |
450 |
|
|
int shut = 0; |
451 |
|
|
|
452 |
|
|
if (event & EV_READ) { |
453 |
|
|
if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) |
454 |
|
|
fatal("imsg_read error"); |
455 |
|
|
if (n == 0) /* connection closed */ |
456 |
|
|
shut = 1; |
457 |
|
|
} |
458 |
|
|
if (event & EV_WRITE) { |
459 |
|
|
if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) |
460 |
|
|
fatal("msgbuf_write"); |
461 |
|
|
if (n == 0) |
462 |
|
|
shut = 1; |
463 |
|
|
} |
464 |
|
|
|
465 |
|
|
for (;;) { |
466 |
|
|
if ((n = imsg_get(ibuf, &imsg)) == -1) |
467 |
|
|
fatal("imsg_get"); |
468 |
|
|
|
469 |
|
|
if (n == 0) |
470 |
|
|
break; |
471 |
|
|
|
472 |
|
|
switch (imsg.hdr.type) { |
473 |
|
|
case IMSG_KLABEL_CHANGE: |
474 |
|
|
if (imsg.hdr.len - IMSG_HEADER_SIZE != |
475 |
|
|
sizeof(struct kroute)) |
476 |
|
|
fatalx("invalid size of IMSG_KLABEL_CHANGE"); |
477 |
|
|
if (kr_change(imsg.data)) |
478 |
|
|
log_warnx("%s: error changing route", __func__); |
479 |
|
|
break; |
480 |
|
|
case IMSG_KLABEL_DELETE: |
481 |
|
|
if (imsg.hdr.len - IMSG_HEADER_SIZE != |
482 |
|
|
sizeof(struct kroute)) |
483 |
|
|
fatalx("invalid size of IMSG_KLABEL_DELETE"); |
484 |
|
|
if (kr_delete(imsg.data)) |
485 |
|
|
log_warnx("%s: error deleting route", __func__); |
486 |
|
|
break; |
487 |
|
|
case IMSG_KPWLABEL_CHANGE: |
488 |
|
|
if (imsg.hdr.len - IMSG_HEADER_SIZE != |
489 |
|
|
sizeof(struct kpw)) |
490 |
|
|
fatalx("invalid size of IMSG_KPWLABEL_CHANGE"); |
491 |
|
|
if (kmpw_set(imsg.data)) |
492 |
|
|
log_warnx("%s: error changing pseudowire", |
493 |
|
|
__func__); |
494 |
|
|
break; |
495 |
|
|
case IMSG_KPWLABEL_DELETE: |
496 |
|
|
if (imsg.hdr.len - IMSG_HEADER_SIZE != |
497 |
|
|
sizeof(struct kpw)) |
498 |
|
|
fatalx("invalid size of IMSG_KPWLABEL_DELETE"); |
499 |
|
|
if (kmpw_unset(imsg.data)) |
500 |
|
|
log_warnx("%s: error unsetting pseudowire", |
501 |
|
|
__func__); |
502 |
|
|
break; |
503 |
|
|
default: |
504 |
|
|
log_debug("%s: error handling imsg %d", __func__, |
505 |
|
|
imsg.hdr.type); |
506 |
|
|
break; |
507 |
|
|
} |
508 |
|
|
imsg_free(&imsg); |
509 |
|
|
} |
510 |
|
|
if (!shut) |
511 |
|
|
imsg_event_add(iev); |
512 |
|
|
else { |
513 |
|
|
/* this pipe is dead, so remove the event handler */ |
514 |
|
|
event_del(&iev->ev); |
515 |
|
|
event_loopexit(NULL); |
516 |
|
|
} |
517 |
|
|
} |
518 |
|
|
|
519 |
|
|
void |
520 |
|
|
main_imsg_compose_ldpe(int type, pid_t pid, void *data, uint16_t datalen) |
521 |
|
|
{ |
522 |
|
|
if (iev_ldpe == NULL) |
523 |
|
|
return; |
524 |
|
|
imsg_compose_event(iev_ldpe, type, 0, pid, -1, data, datalen); |
525 |
|
|
} |
526 |
|
|
|
527 |
|
|
void |
528 |
|
|
main_imsg_compose_lde(int type, pid_t pid, void *data, uint16_t datalen) |
529 |
|
|
{ |
530 |
|
|
imsg_compose_event(iev_lde, type, 0, pid, -1, data, datalen); |
531 |
|
|
} |
532 |
|
|
|
533 |
|
|
static int |
534 |
|
|
main_imsg_compose_both(enum imsg_type type, void *buf, uint16_t len) |
535 |
|
|
{ |
536 |
|
|
if (imsg_compose_event(iev_ldpe, type, 0, 0, -1, buf, len) == -1) |
537 |
|
|
return (-1); |
538 |
|
|
if (imsg_compose_event(iev_lde, type, 0, 0, -1, buf, len) == -1) |
539 |
|
|
return (-1); |
540 |
|
|
return (0); |
541 |
|
|
} |
542 |
|
|
|
543 |
|
|
void |
544 |
|
|
imsg_event_add(struct imsgev *iev) |
545 |
|
|
{ |
546 |
|
|
iev->events = EV_READ; |
547 |
|
|
if (iev->ibuf.w.queued) |
548 |
|
|
iev->events |= EV_WRITE; |
549 |
|
|
|
550 |
|
|
event_del(&iev->ev); |
551 |
|
|
event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev); |
552 |
|
|
event_add(&iev->ev, NULL); |
553 |
|
|
} |
554 |
|
|
|
555 |
|
|
int |
556 |
|
|
imsg_compose_event(struct imsgev *iev, uint16_t type, uint32_t peerid, |
557 |
|
|
pid_t pid, int fd, void *data, uint16_t datalen) |
558 |
|
|
{ |
559 |
|
|
int ret; |
560 |
|
|
|
561 |
|
|
if ((ret = imsg_compose(&iev->ibuf, type, peerid, |
562 |
|
|
pid, fd, data, datalen)) != -1) |
563 |
|
|
imsg_event_add(iev); |
564 |
|
|
return (ret); |
565 |
|
|
} |
566 |
|
|
|
567 |
|
|
void |
568 |
|
|
evbuf_enqueue(struct evbuf *eb, struct ibuf *buf) |
569 |
|
|
{ |
570 |
|
|
ibuf_close(&eb->wbuf, buf); |
571 |
|
|
evbuf_event_add(eb); |
572 |
|
|
} |
573 |
|
|
|
574 |
|
|
void |
575 |
|
|
evbuf_event_add(struct evbuf *eb) |
576 |
|
|
{ |
577 |
|
|
if (eb->wbuf.queued) |
578 |
|
|
event_add(&eb->ev, NULL); |
579 |
|
|
} |
580 |
|
|
|
581 |
|
|
void |
582 |
|
|
evbuf_init(struct evbuf *eb, int fd, void (*handler)(int, short, void *), |
583 |
|
|
void *arg) |
584 |
|
|
{ |
585 |
|
|
msgbuf_init(&eb->wbuf); |
586 |
|
|
eb->wbuf.fd = fd; |
587 |
|
|
event_set(&eb->ev, eb->wbuf.fd, EV_WRITE, handler, arg); |
588 |
|
|
} |
589 |
|
|
|
590 |
|
|
void |
591 |
|
|
evbuf_clear(struct evbuf *eb) |
592 |
|
|
{ |
593 |
|
|
event_del(&eb->ev); |
594 |
|
|
msgbuf_clear(&eb->wbuf); |
595 |
|
|
eb->wbuf.fd = -1; |
596 |
|
|
} |
597 |
|
|
|
598 |
|
|
static int |
599 |
|
|
main_imsg_send_ipc_sockets(struct imsgbuf *ldpe_buf, struct imsgbuf *lde_buf) |
600 |
|
|
{ |
601 |
|
|
int pipe_ldpe2lde[2]; |
602 |
|
|
|
603 |
|
|
if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, |
604 |
|
|
PF_UNSPEC, pipe_ldpe2lde) == -1) |
605 |
|
|
return (-1); |
606 |
|
|
|
607 |
|
|
if (imsg_compose(ldpe_buf, IMSG_SOCKET_IPC, 0, 0, pipe_ldpe2lde[0], |
608 |
|
|
NULL, 0) == -1) |
609 |
|
|
return (-1); |
610 |
|
|
if (imsg_compose(lde_buf, IMSG_SOCKET_IPC, 0, 0, pipe_ldpe2lde[1], |
611 |
|
|
NULL, 0) == -1) |
612 |
|
|
return (-1); |
613 |
|
|
|
614 |
|
|
return (0); |
615 |
|
|
} |
616 |
|
|
|
617 |
|
|
static void |
618 |
|
|
main_imsg_send_net_sockets(int af) |
619 |
|
|
{ |
620 |
|
|
main_imsg_send_net_socket(af, LDP_SOCKET_DISC); |
621 |
|
|
main_imsg_send_net_socket(af, LDP_SOCKET_EDISC); |
622 |
|
|
main_imsg_send_net_socket(af, LDP_SOCKET_SESSION); |
623 |
|
|
imsg_compose_event(iev_ldpe, IMSG_SETUP_SOCKETS, af, 0, -1, NULL, 0); |
624 |
|
|
} |
625 |
|
|
|
626 |
|
|
static void |
627 |
|
|
main_imsg_send_net_socket(int af, enum socket_type type) |
628 |
|
|
{ |
629 |
|
|
int fd; |
630 |
|
|
|
631 |
|
|
fd = ldp_create_socket(af, type); |
632 |
|
|
if (fd == -1) { |
633 |
|
|
log_warnx("%s: failed to create %s socket for address-family " |
634 |
|
|
"%s", __func__, socket_name(type), af_name(af)); |
635 |
|
|
return; |
636 |
|
|
} |
637 |
|
|
|
638 |
|
|
imsg_compose_event(iev_ldpe, IMSG_SOCKET_NET, af, 0, fd, &type, |
639 |
|
|
sizeof(type)); |
640 |
|
|
} |
641 |
|
|
|
642 |
|
|
struct ldpd_af_conf * |
643 |
|
|
ldp_af_conf_get(struct ldpd_conf *xconf, int af) |
644 |
|
|
{ |
645 |
|
|
switch (af) { |
646 |
|
|
case AF_INET: |
647 |
|
|
return (&xconf->ipv4); |
648 |
|
|
case AF_INET6: |
649 |
|
|
return (&xconf->ipv6); |
650 |
|
|
default: |
651 |
|
|
fatalx("ldp_af_conf_get: unknown af"); |
652 |
|
|
} |
653 |
|
|
} |
654 |
|
|
|
655 |
|
|
struct ldpd_af_global * |
656 |
|
|
ldp_af_global_get(struct ldpd_global *xglobal, int af) |
657 |
|
|
{ |
658 |
|
|
switch (af) { |
659 |
|
|
case AF_INET: |
660 |
|
|
return (&xglobal->ipv4); |
661 |
|
|
case AF_INET6: |
662 |
|
|
return (&xglobal->ipv6); |
663 |
|
|
default: |
664 |
|
|
fatalx("ldp_af_global_get: unknown af"); |
665 |
|
|
} |
666 |
|
|
} |
667 |
|
|
|
668 |
|
|
int |
669 |
|
|
ldp_is_dual_stack(struct ldpd_conf *xconf) |
670 |
|
|
{ |
671 |
|
|
return ((xconf->ipv4.flags & F_LDPD_AF_ENABLED) && |
672 |
|
|
(xconf->ipv6.flags & F_LDPD_AF_ENABLED)); |
673 |
|
|
} |
674 |
|
|
|
675 |
|
|
static int |
676 |
|
|
main_imsg_send_config(struct ldpd_conf *xconf) |
677 |
|
|
{ |
678 |
|
|
struct iface *iface; |
679 |
|
|
struct tnbr *tnbr; |
680 |
|
|
struct nbr_params *nbrp; |
681 |
|
|
struct l2vpn *l2vpn; |
682 |
|
|
struct l2vpn_if *lif; |
683 |
|
|
struct l2vpn_pw *pw; |
684 |
|
|
|
685 |
|
|
if (main_imsg_compose_both(IMSG_RECONF_CONF, xconf, |
686 |
|
|
sizeof(*xconf)) == -1) |
687 |
|
|
return (-1); |
688 |
|
|
|
689 |
|
|
LIST_FOREACH(iface, &xconf->iface_list, entry) { |
690 |
|
|
if (main_imsg_compose_both(IMSG_RECONF_IFACE, iface, |
691 |
|
|
sizeof(*iface)) == -1) |
692 |
|
|
return (-1); |
693 |
|
|
} |
694 |
|
|
|
695 |
|
|
LIST_FOREACH(tnbr, &xconf->tnbr_list, entry) { |
696 |
|
|
if (main_imsg_compose_both(IMSG_RECONF_TNBR, tnbr, |
697 |
|
|
sizeof(*tnbr)) == -1) |
698 |
|
|
return (-1); |
699 |
|
|
} |
700 |
|
|
|
701 |
|
|
LIST_FOREACH(nbrp, &xconf->nbrp_list, entry) { |
702 |
|
|
if (main_imsg_compose_both(IMSG_RECONF_NBRP, nbrp, |
703 |
|
|
sizeof(*nbrp)) == -1) |
704 |
|
|
return (-1); |
705 |
|
|
} |
706 |
|
|
|
707 |
|
|
LIST_FOREACH(l2vpn, &xconf->l2vpn_list, entry) { |
708 |
|
|
if (main_imsg_compose_both(IMSG_RECONF_L2VPN, l2vpn, |
709 |
|
|
sizeof(*l2vpn)) == -1) |
710 |
|
|
return (-1); |
711 |
|
|
|
712 |
|
|
LIST_FOREACH(lif, &l2vpn->if_list, entry) { |
713 |
|
|
if (main_imsg_compose_both(IMSG_RECONF_L2VPN_IF, lif, |
714 |
|
|
sizeof(*lif)) == -1) |
715 |
|
|
return (-1); |
716 |
|
|
} |
717 |
|
|
LIST_FOREACH(pw, &l2vpn->pw_list, entry) { |
718 |
|
|
if (main_imsg_compose_both(IMSG_RECONF_L2VPN_PW, pw, |
719 |
|
|
sizeof(*pw)) == -1) |
720 |
|
|
return (-1); |
721 |
|
|
} |
722 |
|
|
} |
723 |
|
|
|
724 |
|
|
if (main_imsg_compose_both(IMSG_RECONF_END, NULL, 0) == -1) |
725 |
|
|
return (-1); |
726 |
|
|
|
727 |
|
|
return (0); |
728 |
|
|
} |
729 |
|
|
|
730 |
|
|
static int |
731 |
|
|
ldp_reload(void) |
732 |
|
|
{ |
733 |
|
|
struct ldpd_conf *xconf; |
734 |
|
|
|
735 |
|
|
if ((xconf = parse_config(conffile)) == NULL) |
736 |
|
|
return (-1); |
737 |
|
|
|
738 |
|
|
if (main_imsg_send_config(xconf) == -1) |
739 |
|
|
return (-1); |
740 |
|
|
|
741 |
|
|
merge_config(ldpd_conf, xconf); |
742 |
|
|
|
743 |
|
|
return (0); |
744 |
|
|
} |
745 |
|
|
|
746 |
|
|
void |
747 |
|
|
merge_config(struct ldpd_conf *conf, struct ldpd_conf *xconf) |
748 |
|
|
{ |
749 |
|
|
merge_global(conf, xconf); |
750 |
|
|
merge_af(AF_INET, &conf->ipv4, &xconf->ipv4); |
751 |
|
|
merge_af(AF_INET6, &conf->ipv6, &xconf->ipv6); |
752 |
|
|
merge_ifaces(conf, xconf); |
753 |
|
|
merge_tnbrs(conf, xconf); |
754 |
|
|
merge_nbrps(conf, xconf); |
755 |
|
|
merge_l2vpns(conf, xconf); |
756 |
|
|
free(xconf); |
757 |
|
|
} |
758 |
|
|
|
759 |
|
|
static void |
760 |
|
|
merge_global(struct ldpd_conf *conf, struct ldpd_conf *xconf) |
761 |
|
|
{ |
762 |
|
|
/* change of router-id requires resetting all neighborships */ |
763 |
|
|
if (conf->rtr_id.s_addr != xconf->rtr_id.s_addr) { |
764 |
|
|
if (ldpd_process == PROC_LDP_ENGINE) { |
765 |
|
|
ldpe_reset_nbrs(AF_INET); |
766 |
|
|
ldpe_reset_nbrs(AF_INET6); |
767 |
|
|
if (conf->rtr_id.s_addr == INADDR_ANY || |
768 |
|
|
xconf->rtr_id.s_addr == INADDR_ANY) { |
769 |
|
|
if_update_all(AF_UNSPEC); |
770 |
|
|
tnbr_update_all(AF_UNSPEC); |
771 |
|
|
} |
772 |
|
|
} |
773 |
|
|
conf->rtr_id = xconf->rtr_id; |
774 |
|
|
} |
775 |
|
|
|
776 |
|
|
conf->rdomain= xconf->rdomain; |
777 |
|
|
|
778 |
|
|
if (conf->trans_pref != xconf->trans_pref) { |
779 |
|
|
if (ldpd_process == PROC_LDP_ENGINE) |
780 |
|
|
ldpe_reset_ds_nbrs(); |
781 |
|
|
conf->trans_pref = xconf->trans_pref; |
782 |
|
|
} |
783 |
|
|
|
784 |
|
|
if ((conf->flags & F_LDPD_DS_CISCO_INTEROP) != |
785 |
|
|
(xconf->flags & F_LDPD_DS_CISCO_INTEROP)) { |
786 |
|
|
if (ldpd_process == PROC_LDP_ENGINE) |
787 |
|
|
ldpe_reset_ds_nbrs(); |
788 |
|
|
} |
789 |
|
|
|
790 |
|
|
conf->flags = xconf->flags; |
791 |
|
|
} |
792 |
|
|
|
793 |
|
|
static void |
794 |
|
|
merge_af(int af, struct ldpd_af_conf *af_conf, struct ldpd_af_conf *xa) |
795 |
|
|
{ |
796 |
|
|
int egress_label_changed = 0; |
797 |
|
|
int update_sockets = 0; |
798 |
|
|
|
799 |
|
|
if (af_conf->keepalive != xa->keepalive) { |
800 |
|
|
af_conf->keepalive = xa->keepalive; |
801 |
|
|
if (ldpd_process == PROC_LDP_ENGINE) |
802 |
|
|
ldpe_stop_init_backoff(af); |
803 |
|
|
} |
804 |
|
|
af_conf->thello_holdtime = xa->thello_holdtime; |
805 |
|
|
af_conf->thello_interval = xa->thello_interval; |
806 |
|
|
|
807 |
|
|
/* update flags */ |
808 |
|
|
if (ldpd_process == PROC_LDP_ENGINE && |
809 |
|
|
(af_conf->flags & F_LDPD_AF_THELLO_ACCEPT) && |
810 |
|
|
!(xa->flags & F_LDPD_AF_THELLO_ACCEPT)) |
811 |
|
|
ldpe_remove_dynamic_tnbrs(af); |
812 |
|
|
|
813 |
|
|
if ((af_conf->flags & F_LDPD_AF_NO_GTSM) != |
814 |
|
|
(xa->flags & F_LDPD_AF_NO_GTSM)) { |
815 |
|
|
if (af == AF_INET6) |
816 |
|
|
/* need to set/unset IPV6_MINHOPCOUNT */ |
817 |
|
|
update_sockets = 1; |
818 |
|
|
else if (ldpd_process == PROC_LDP_ENGINE) |
819 |
|
|
/* for LDPv4 just resetting the neighbors is enough */ |
820 |
|
|
ldpe_reset_nbrs(af); |
821 |
|
|
} |
822 |
|
|
|
823 |
|
|
if ((af_conf->flags & F_LDPD_AF_EXPNULL) != |
824 |
|
|
(xa->flags & F_LDPD_AF_EXPNULL)) |
825 |
|
|
egress_label_changed = 1; |
826 |
|
|
|
827 |
|
|
af_conf->flags = xa->flags; |
828 |
|
|
|
829 |
|
|
if (egress_label_changed) { |
830 |
|
|
switch (ldpd_process) { |
831 |
|
|
case PROC_LDE_ENGINE: |
832 |
|
|
lde_change_egress_label(af, af_conf->flags & |
833 |
|
|
F_LDPD_AF_EXPNULL); |
834 |
|
|
break; |
835 |
|
|
case PROC_MAIN: |
836 |
|
|
kr_change_egress_label(af, af_conf->flags & |
837 |
|
|
F_LDPD_AF_EXPNULL); |
838 |
|
|
break; |
839 |
|
|
default: |
840 |
|
|
break; |
841 |
|
|
} |
842 |
|
|
} |
843 |
|
|
|
844 |
|
|
if (ldp_addrcmp(af, &af_conf->trans_addr, &xa->trans_addr)) { |
845 |
|
|
af_conf->trans_addr = xa->trans_addr; |
846 |
|
|
update_sockets = 1; |
847 |
|
|
} |
848 |
|
|
|
849 |
|
|
if (ldpd_process == PROC_MAIN && update_sockets) |
850 |
|
|
imsg_compose_event(iev_ldpe, IMSG_CLOSE_SOCKETS, af, 0, -1, |
851 |
|
|
NULL, 0); |
852 |
|
|
} |
853 |
|
|
|
854 |
|
|
static void |
855 |
|
|
merge_ifaces(struct ldpd_conf *conf, struct ldpd_conf *xconf) |
856 |
|
|
{ |
857 |
|
|
struct iface *iface, *itmp, *xi; |
858 |
|
|
|
859 |
|
|
LIST_FOREACH_SAFE(iface, &conf->iface_list, entry, itmp) { |
860 |
|
|
/* find deleted interfaces */ |
861 |
|
|
if ((xi = if_lookup(xconf, iface->ifindex)) == NULL) { |
862 |
|
|
LIST_REMOVE(iface, entry); |
863 |
|
|
if (ldpd_process == PROC_LDP_ENGINE) |
864 |
|
|
if_exit(iface); |
865 |
|
|
free(iface); |
866 |
|
|
} |
867 |
|
|
} |
868 |
|
|
LIST_FOREACH_SAFE(xi, &xconf->iface_list, entry, itmp) { |
869 |
|
|
/* find new interfaces */ |
870 |
|
|
if ((iface = if_lookup(conf, xi->ifindex)) == NULL) { |
871 |
|
|
LIST_REMOVE(xi, entry); |
872 |
|
|
LIST_INSERT_HEAD(&conf->iface_list, xi, entry); |
873 |
|
|
|
874 |
|
|
/* resend addresses to activate new interfaces */ |
875 |
|
|
if (ldpd_process == PROC_MAIN) |
876 |
|
|
kif_redistribute(xi->name); |
877 |
|
|
continue; |
878 |
|
|
} |
879 |
|
|
|
880 |
|
|
/* update existing interfaces */ |
881 |
|
|
merge_iface_af(&iface->ipv4, &xi->ipv4); |
882 |
|
|
merge_iface_af(&iface->ipv6, &xi->ipv6); |
883 |
|
|
LIST_REMOVE(xi, entry); |
884 |
|
|
free(xi); |
885 |
|
|
} |
886 |
|
|
} |
887 |
|
|
|
888 |
|
|
static void |
889 |
|
|
merge_iface_af(struct iface_af *ia, struct iface_af *xi) |
890 |
|
|
{ |
891 |
|
|
if (ia->enabled != xi->enabled) { |
892 |
|
|
ia->enabled = xi->enabled; |
893 |
|
|
if (ldpd_process == PROC_LDP_ENGINE) |
894 |
|
|
if_update(ia->iface, ia->af); |
895 |
|
|
} |
896 |
|
|
ia->hello_holdtime = xi->hello_holdtime; |
897 |
|
|
ia->hello_interval = xi->hello_interval; |
898 |
|
|
} |
899 |
|
|
|
900 |
|
|
static void |
901 |
|
|
merge_tnbrs(struct ldpd_conf *conf, struct ldpd_conf *xconf) |
902 |
|
|
{ |
903 |
|
|
struct tnbr *tnbr, *ttmp, *xt; |
904 |
|
|
|
905 |
|
|
LIST_FOREACH_SAFE(tnbr, &conf->tnbr_list, entry, ttmp) { |
906 |
|
|
if (!(tnbr->flags & F_TNBR_CONFIGURED)) |
907 |
|
|
continue; |
908 |
|
|
|
909 |
|
|
/* find deleted tnbrs */ |
910 |
|
|
if ((xt = tnbr_find(xconf, tnbr->af, &tnbr->addr)) == NULL) { |
911 |
|
|
if (ldpd_process == PROC_LDP_ENGINE) { |
912 |
|
|
tnbr->flags &= ~F_TNBR_CONFIGURED; |
913 |
|
|
tnbr_check(tnbr); |
914 |
|
|
} else { |
915 |
|
|
LIST_REMOVE(tnbr, entry); |
916 |
|
|
free(tnbr); |
917 |
|
|
} |
918 |
|
|
} |
919 |
|
|
} |
920 |
|
|
LIST_FOREACH_SAFE(xt, &xconf->tnbr_list, entry, ttmp) { |
921 |
|
|
/* find new tnbrs */ |
922 |
|
|
if ((tnbr = tnbr_find(conf, xt->af, &xt->addr)) == NULL) { |
923 |
|
|
LIST_REMOVE(xt, entry); |
924 |
|
|
LIST_INSERT_HEAD(&conf->tnbr_list, xt, entry); |
925 |
|
|
|
926 |
|
|
if (ldpd_process == PROC_LDP_ENGINE) |
927 |
|
|
tnbr_update(xt); |
928 |
|
|
continue; |
929 |
|
|
} |
930 |
|
|
|
931 |
|
|
/* update existing tnbrs */ |
932 |
|
|
if (!(tnbr->flags & F_TNBR_CONFIGURED)) |
933 |
|
|
tnbr->flags |= F_TNBR_CONFIGURED; |
934 |
|
|
tnbr->hello_holdtime = xt->hello_holdtime; |
935 |
|
|
tnbr->hello_interval = xt->hello_interval; |
936 |
|
|
LIST_REMOVE(xt, entry); |
937 |
|
|
free(xt); |
938 |
|
|
} |
939 |
|
|
} |
940 |
|
|
|
941 |
|
|
static void |
942 |
|
|
merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf) |
943 |
|
|
{ |
944 |
|
|
struct nbr_params *nbrp, *ntmp, *xn; |
945 |
|
|
struct nbr *nbr; |
946 |
|
|
int nbrp_changed; |
947 |
|
|
|
948 |
|
|
LIST_FOREACH_SAFE(nbrp, &conf->nbrp_list, entry, ntmp) { |
949 |
|
|
/* find deleted nbrps */ |
950 |
|
|
if ((xn = nbr_params_find(xconf, nbrp->lsr_id)) == NULL) { |
951 |
|
|
if (ldpd_process == PROC_LDP_ENGINE) { |
952 |
|
|
nbr = nbr_find_ldpid(nbrp->lsr_id.s_addr); |
953 |
|
|
if (nbr) { |
954 |
|
|
session_shutdown(nbr, S_SHUTDOWN, 0, 0); |
955 |
|
|
pfkey_remove(nbr); |
956 |
|
|
if (nbr_session_active_role(nbr)) |
957 |
|
|
nbr_establish_connection(nbr); |
958 |
|
|
} |
959 |
|
|
} |
960 |
|
|
LIST_REMOVE(nbrp, entry); |
961 |
|
|
free(nbrp); |
962 |
|
|
} |
963 |
|
|
} |
964 |
|
|
LIST_FOREACH_SAFE(xn, &xconf->nbrp_list, entry, ntmp) { |
965 |
|
|
/* find new nbrps */ |
966 |
|
|
if ((nbrp = nbr_params_find(conf, xn->lsr_id)) == NULL) { |
967 |
|
|
LIST_REMOVE(xn, entry); |
968 |
|
|
LIST_INSERT_HEAD(&conf->nbrp_list, xn, entry); |
969 |
|
|
|
970 |
|
|
if (ldpd_process == PROC_LDP_ENGINE) { |
971 |
|
|
nbr = nbr_find_ldpid(xn->lsr_id.s_addr); |
972 |
|
|
if (nbr) { |
973 |
|
|
session_shutdown(nbr, S_SHUTDOWN, 0, 0); |
974 |
|
|
if (pfkey_establish(nbr, xn) == -1) |
975 |
|
|
fatalx("pfkey setup failed"); |
976 |
|
|
if (nbr_session_active_role(nbr)) |
977 |
|
|
nbr_establish_connection(nbr); |
978 |
|
|
} |
979 |
|
|
} |
980 |
|
|
continue; |
981 |
|
|
} |
982 |
|
|
|
983 |
|
|
/* update existing nbrps */ |
984 |
|
|
if (nbrp->flags != xn->flags || |
985 |
|
|
nbrp->keepalive != xn->keepalive || |
986 |
|
|
nbrp->gtsm_enabled != xn->gtsm_enabled || |
987 |
|
|
nbrp->gtsm_hops != xn->gtsm_hops || |
988 |
|
|
nbrp->auth.method != xn->auth.method || |
989 |
|
|
strcmp(nbrp->auth.md5key, xn->auth.md5key) != 0) |
990 |
|
|
nbrp_changed = 1; |
991 |
|
|
else |
992 |
|
|
nbrp_changed = 0; |
993 |
|
|
|
994 |
|
|
nbrp->keepalive = xn->keepalive; |
995 |
|
|
nbrp->gtsm_enabled = xn->gtsm_enabled; |
996 |
|
|
nbrp->gtsm_hops = xn->gtsm_hops; |
997 |
|
|
nbrp->auth.method = xn->auth.method; |
998 |
|
|
strlcpy(nbrp->auth.md5key, xn->auth.md5key, |
999 |
|
|
sizeof(nbrp->auth.md5key)); |
1000 |
|
|
nbrp->auth.md5key_len = xn->auth.md5key_len; |
1001 |
|
|
nbrp->flags = xn->flags; |
1002 |
|
|
|
1003 |
|
|
if (ldpd_process == PROC_LDP_ENGINE) { |
1004 |
|
|
nbr = nbr_find_ldpid(nbrp->lsr_id.s_addr); |
1005 |
|
|
if (nbr && nbrp_changed) { |
1006 |
|
|
session_shutdown(nbr, S_SHUTDOWN, 0, 0); |
1007 |
|
|
pfkey_remove(nbr); |
1008 |
|
|
if (pfkey_establish(nbr, nbrp) == -1) |
1009 |
|
|
fatalx("pfkey setup failed"); |
1010 |
|
|
if (nbr_session_active_role(nbr)) |
1011 |
|
|
nbr_establish_connection(nbr); |
1012 |
|
|
} |
1013 |
|
|
} |
1014 |
|
|
LIST_REMOVE(xn, entry); |
1015 |
|
|
free(xn); |
1016 |
|
|
} |
1017 |
|
|
} |
1018 |
|
|
|
1019 |
|
|
static void |
1020 |
|
|
merge_l2vpns(struct ldpd_conf *conf, struct ldpd_conf *xconf) |
1021 |
|
|
{ |
1022 |
|
|
struct l2vpn *l2vpn, *ltmp, *xl; |
1023 |
|
|
|
1024 |
|
|
LIST_FOREACH_SAFE(l2vpn, &conf->l2vpn_list, entry, ltmp) { |
1025 |
|
|
/* find deleted l2vpns */ |
1026 |
|
|
if ((xl = l2vpn_find(xconf, l2vpn->name)) == NULL) { |
1027 |
|
|
LIST_REMOVE(l2vpn, entry); |
1028 |
|
|
|
1029 |
|
|
switch (ldpd_process) { |
1030 |
|
|
case PROC_LDE_ENGINE: |
1031 |
|
|
l2vpn_exit(l2vpn); |
1032 |
|
|
break; |
1033 |
|
|
case PROC_LDP_ENGINE: |
1034 |
|
|
ldpe_l2vpn_exit(l2vpn); |
1035 |
|
|
break; |
1036 |
|
|
case PROC_MAIN: |
1037 |
|
|
break; |
1038 |
|
|
} |
1039 |
|
|
l2vpn_del(l2vpn); |
1040 |
|
|
} |
1041 |
|
|
} |
1042 |
|
|
LIST_FOREACH_SAFE(xl, &xconf->l2vpn_list, entry, ltmp) { |
1043 |
|
|
/* find new l2vpns */ |
1044 |
|
|
if ((l2vpn = l2vpn_find(conf, xl->name)) == NULL) { |
1045 |
|
|
LIST_REMOVE(xl, entry); |
1046 |
|
|
LIST_INSERT_HEAD(&conf->l2vpn_list, xl, entry); |
1047 |
|
|
|
1048 |
|
|
switch (ldpd_process) { |
1049 |
|
|
case PROC_LDE_ENGINE: |
1050 |
|
|
l2vpn_init(xl); |
1051 |
|
|
break; |
1052 |
|
|
case PROC_LDP_ENGINE: |
1053 |
|
|
ldpe_l2vpn_init(xl); |
1054 |
|
|
break; |
1055 |
|
|
case PROC_MAIN: |
1056 |
|
|
break; |
1057 |
|
|
} |
1058 |
|
|
continue; |
1059 |
|
|
} |
1060 |
|
|
|
1061 |
|
|
/* update existing l2vpns */ |
1062 |
|
|
merge_l2vpn(conf, l2vpn, xl); |
1063 |
|
|
LIST_REMOVE(xl, entry); |
1064 |
|
|
free(xl); |
1065 |
|
|
} |
1066 |
|
|
} |
1067 |
|
|
|
1068 |
|
|
static void |
1069 |
|
|
merge_l2vpn(struct ldpd_conf *xconf, struct l2vpn *l2vpn, struct l2vpn *xl) |
1070 |
|
|
{ |
1071 |
|
|
struct l2vpn_if *lif, *ftmp, *xf; |
1072 |
|
|
struct l2vpn_pw *pw, *ptmp, *xp; |
1073 |
|
|
struct nbr *nbr; |
1074 |
|
|
int reset_nbr, reinstall_pwfec, reinstall_tnbr; |
1075 |
|
|
int previous_pw_type, previous_mtu; |
1076 |
|
|
|
1077 |
|
|
previous_pw_type = l2vpn->pw_type; |
1078 |
|
|
previous_mtu = l2vpn->mtu; |
1079 |
|
|
|
1080 |
|
|
/* merge intefaces */ |
1081 |
|
|
LIST_FOREACH_SAFE(lif, &l2vpn->if_list, entry, ftmp) { |
1082 |
|
|
/* find deleted interfaces */ |
1083 |
|
|
if ((xf = l2vpn_if_find(xl, lif->ifindex)) == NULL) { |
1084 |
|
|
LIST_REMOVE(lif, entry); |
1085 |
|
|
free(lif); |
1086 |
|
|
} |
1087 |
|
|
} |
1088 |
|
|
LIST_FOREACH_SAFE(xf, &xl->if_list, entry, ftmp) { |
1089 |
|
|
/* find new interfaces */ |
1090 |
|
|
if ((lif = l2vpn_if_find(l2vpn, xf->ifindex)) == NULL) { |
1091 |
|
|
LIST_REMOVE(xf, entry); |
1092 |
|
|
LIST_INSERT_HEAD(&l2vpn->if_list, xf, entry); |
1093 |
|
|
xf->l2vpn = l2vpn; |
1094 |
|
|
continue; |
1095 |
|
|
} |
1096 |
|
|
|
1097 |
|
|
LIST_REMOVE(xf, entry); |
1098 |
|
|
free(xf); |
1099 |
|
|
} |
1100 |
|
|
|
1101 |
|
|
/* merge pseudowires */ |
1102 |
|
|
LIST_FOREACH_SAFE(pw, &l2vpn->pw_list, entry, ptmp) { |
1103 |
|
|
/* find deleted pseudowires */ |
1104 |
|
|
if ((xp = l2vpn_pw_find(xl, pw->ifindex)) == NULL) { |
1105 |
|
|
switch (ldpd_process) { |
1106 |
|
|
case PROC_LDE_ENGINE: |
1107 |
|
|
l2vpn_pw_exit(pw); |
1108 |
|
|
break; |
1109 |
|
|
case PROC_LDP_ENGINE: |
1110 |
|
|
ldpe_l2vpn_pw_exit(pw); |
1111 |
|
|
break; |
1112 |
|
|
case PROC_MAIN: |
1113 |
|
|
break; |
1114 |
|
|
} |
1115 |
|
|
|
1116 |
|
|
LIST_REMOVE(pw, entry); |
1117 |
|
|
free(pw); |
1118 |
|
|
} |
1119 |
|
|
} |
1120 |
|
|
LIST_FOREACH_SAFE(xp, &xl->pw_list, entry, ptmp) { |
1121 |
|
|
/* find new pseudowires */ |
1122 |
|
|
if ((pw = l2vpn_pw_find(l2vpn, xp->ifindex)) == NULL) { |
1123 |
|
|
LIST_REMOVE(xp, entry); |
1124 |
|
|
LIST_INSERT_HEAD(&l2vpn->pw_list, xp, entry); |
1125 |
|
|
xp->l2vpn = l2vpn; |
1126 |
|
|
|
1127 |
|
|
switch (ldpd_process) { |
1128 |
|
|
case PROC_LDE_ENGINE: |
1129 |
|
|
l2vpn_pw_init(xp); |
1130 |
|
|
break; |
1131 |
|
|
case PROC_LDP_ENGINE: |
1132 |
|
|
ldpe_l2vpn_pw_init(xp); |
1133 |
|
|
break; |
1134 |
|
|
case PROC_MAIN: |
1135 |
|
|
break; |
1136 |
|
|
} |
1137 |
|
|
continue; |
1138 |
|
|
} |
1139 |
|
|
|
1140 |
|
|
/* update existing pseudowire */ |
1141 |
|
|
if (pw->af != xp->af || |
1142 |
|
|
ldp_addrcmp(pw->af, &pw->addr, &xp->addr)) |
1143 |
|
|
reinstall_tnbr = 1; |
1144 |
|
|
else |
1145 |
|
|
reinstall_tnbr = 0; |
1146 |
|
|
|
1147 |
|
|
/* changes that require a session restart */ |
1148 |
|
|
if ((pw->flags & (F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF)) != |
1149 |
|
|
(xp->flags & (F_PW_STATUSTLV_CONF|F_PW_CWORD_CONF))) |
1150 |
|
|
reset_nbr = 1; |
1151 |
|
|
else |
1152 |
|
|
reset_nbr = 0; |
1153 |
|
|
|
1154 |
|
|
if (l2vpn->pw_type != xl->pw_type || l2vpn->mtu != xl->mtu || |
1155 |
|
|
pw->pwid != xp->pwid || reinstall_tnbr || reset_nbr || |
1156 |
|
|
pw->lsr_id.s_addr != xp->lsr_id.s_addr) |
1157 |
|
|
reinstall_pwfec = 1; |
1158 |
|
|
else |
1159 |
|
|
reinstall_pwfec = 0; |
1160 |
|
|
|
1161 |
|
|
if (ldpd_process == PROC_LDP_ENGINE) { |
1162 |
|
|
if (reinstall_tnbr) |
1163 |
|
|
ldpe_l2vpn_pw_exit(pw); |
1164 |
|
|
if (reset_nbr) { |
1165 |
|
|
nbr = nbr_find_ldpid(pw->lsr_id.s_addr); |
1166 |
|
|
if (nbr && nbr->state == NBR_STA_OPER) |
1167 |
|
|
session_shutdown(nbr, S_SHUTDOWN, 0, 0); |
1168 |
|
|
} |
1169 |
|
|
} |
1170 |
|
|
if (ldpd_process == PROC_LDE_ENGINE && |
1171 |
|
|
!reset_nbr && reinstall_pwfec) |
1172 |
|
|
l2vpn_pw_exit(pw); |
1173 |
|
|
pw->lsr_id = xp->lsr_id; |
1174 |
|
|
pw->af = xp->af; |
1175 |
|
|
pw->addr = xp->addr; |
1176 |
|
|
pw->pwid = xp->pwid; |
1177 |
|
|
strlcpy(pw->ifname, xp->ifname, sizeof(pw->ifname)); |
1178 |
|
|
pw->ifindex = xp->ifindex; |
1179 |
|
|
if (xp->flags & F_PW_CWORD_CONF) |
1180 |
|
|
pw->flags |= F_PW_CWORD_CONF; |
1181 |
|
|
else |
1182 |
|
|
pw->flags &= ~F_PW_CWORD_CONF; |
1183 |
|
|
if (xp->flags & F_PW_STATUSTLV_CONF) |
1184 |
|
|
pw->flags |= F_PW_STATUSTLV_CONF; |
1185 |
|
|
else |
1186 |
|
|
pw->flags &= ~F_PW_STATUSTLV_CONF; |
1187 |
|
|
if (ldpd_process == PROC_LDP_ENGINE && reinstall_tnbr) |
1188 |
|
|
ldpe_l2vpn_pw_init(pw); |
1189 |
|
|
if (ldpd_process == PROC_LDE_ENGINE && |
1190 |
|
|
!reset_nbr && reinstall_pwfec) { |
1191 |
|
|
l2vpn->pw_type = xl->pw_type; |
1192 |
|
|
l2vpn->mtu = xl->mtu; |
1193 |
|
|
l2vpn_pw_init(pw); |
1194 |
|
|
l2vpn->pw_type = previous_pw_type; |
1195 |
|
|
l2vpn->mtu = previous_mtu; |
1196 |
|
|
} |
1197 |
|
|
|
1198 |
|
|
LIST_REMOVE(xp, entry); |
1199 |
|
|
free(xp); |
1200 |
|
|
} |
1201 |
|
|
|
1202 |
|
|
l2vpn->pw_type = xl->pw_type; |
1203 |
|
|
l2vpn->mtu = xl->mtu; |
1204 |
|
|
strlcpy(l2vpn->br_ifname, xl->br_ifname, sizeof(l2vpn->br_ifname)); |
1205 |
|
|
l2vpn->br_ifindex = xl->br_ifindex; |
1206 |
|
|
} |
1207 |
|
|
|
1208 |
|
|
struct ldpd_conf * |
1209 |
|
|
config_new_empty(void) |
1210 |
|
|
{ |
1211 |
|
|
struct ldpd_conf *xconf; |
1212 |
|
|
|
1213 |
|
|
xconf = calloc(1, sizeof(*xconf)); |
1214 |
|
|
if (xconf == NULL) |
1215 |
|
|
fatal(NULL); |
1216 |
|
|
|
1217 |
|
|
LIST_INIT(&xconf->iface_list); |
1218 |
|
|
LIST_INIT(&xconf->tnbr_list); |
1219 |
|
|
LIST_INIT(&xconf->nbrp_list); |
1220 |
|
|
LIST_INIT(&xconf->l2vpn_list); |
1221 |
|
|
|
1222 |
|
|
return (xconf); |
1223 |
|
|
} |
1224 |
|
|
|
1225 |
|
|
void |
1226 |
|
|
config_clear(struct ldpd_conf *conf) |
1227 |
|
|
{ |
1228 |
|
|
struct ldpd_conf *xconf; |
1229 |
|
|
|
1230 |
|
|
/* |
1231 |
|
|
* Merge current config with an empty config, this will deactivate |
1232 |
|
|
* and deallocate all the interfaces, pseudowires and so on. Before |
1233 |
|
|
* merging, copy the router-id and other variables to avoid some |
1234 |
|
|
* unnecessary operations, like trying to reset the neighborships. |
1235 |
|
|
*/ |
1236 |
|
|
xconf = config_new_empty(); |
1237 |
|
|
xconf->ipv4 = conf->ipv4; |
1238 |
|
|
xconf->ipv6 = conf->ipv6; |
1239 |
|
|
xconf->rtr_id = conf->rtr_id; |
1240 |
|
|
xconf->trans_pref = conf->trans_pref; |
1241 |
|
|
xconf->flags = conf->flags; |
1242 |
|
|
merge_config(conf, xconf); |
1243 |
|
|
free(conf); |
1244 |
|
|
} |