GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/ldpd/ldpd.c Lines: 0 599 0.0 %
Date: 2017-11-07 Branches: 0 471 0.0 %

Line Branch Exec Source
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
}