ldpd.c revision 1.4
1/*	$OpenBSD: ldpd.c,v 1.4 2009/10/28 09:15:58 sobrado Exp $ */
2
3/*
4 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
5 * Copyright (c) 2004, 2008 Esben Norby <norby@openbsd.org>
6 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
7 *
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 */
20
21#include <sys/types.h>
22#include <sys/socket.h>
23#include <sys/queue.h>
24#include <sys/time.h>
25#include <sys/stat.h>
26#include <sys/wait.h>
27#include <sys/param.h>
28#include <sys/sysctl.h>
29
30#include <netinet/in.h>
31#include <arpa/inet.h>
32#include <netmpls/mpls.h>
33
34#include <event.h>
35#include <err.h>
36#include <errno.h>
37#include <pwd.h>
38#include <stdio.h>
39#include <stdlib.h>
40#include <string.h>
41#include <signal.h>
42#include <unistd.h>
43
44#include "ldpd.h"
45#include "ldp.h"
46#include "ldpe.h"
47#include "control.h"
48#include "log.h"
49#include "lde.h"
50
51void		main_sig_handler(int, short, void *);
52__dead void	usage(void);
53void		ldpd_shutdown(void);
54int		check_child(pid_t, const char *);
55
56void	main_dispatch_ldpe(int, short, void *);
57void	main_dispatch_lde(int, short, void *);
58
59/*int	ldp_reload(void); */
60int	ldp_sendboth(enum imsg_type, void *, u_int16_t);
61/*int	merge_interfaces(struct lspace *, struct lspace *); */
62/*struct iface *iface_lookup(struct lspace *, struct iface *); */
63
64int	pipe_parent2ldpe[2];
65int	pipe_parent2lde[2];
66int	pipe_ldpe2lde[2];
67
68struct ldpd_conf	*ldpd_conf = NULL;
69struct imsgev		*iev_ldpe;
70struct imsgev		*iev_lde;
71char			*conffile;
72
73pid_t			 ldpe_pid = 0;
74pid_t			 lde_pid = 0;
75
76/* ARGSUSED */
77void
78main_sig_handler(int sig, short event, void *arg)
79{
80	/*
81	 * signal handler rules don't apply, libevent decouples for us
82	 */
83
84	int	die = 0;
85
86	switch (sig) {
87	case SIGTERM:
88	case SIGINT:
89		die = 1;
90		/* FALLTHROUGH */
91	case SIGCHLD:
92		if (check_child(ldpe_pid, "ldp engine")) {
93			ldpe_pid = 0;
94			die = 1;
95		}
96		if (check_child(lde_pid, "label decision engine")) {
97			lde_pid = 0;
98			die = 1;
99		}
100		if (die)
101			ldpd_shutdown();
102		break;
103	case SIGHUP:
104/*
105		if (ldp_reload() == -1)
106			log_warnx("configuration reload failed");
107		else
108			log_debug("configuration reloaded");
109*/
110		break;
111	default:
112		fatalx("unexpected signal");
113		/* NOTREACHED */
114	}
115}
116
117__dead void
118usage(void)
119{
120	extern char *__progname;
121
122	fprintf(stderr, "usage: %s [-dnv] [-D macro=value] [-f file]\n",
123	    __progname);
124	exit(1);
125}
126
127int
128main(int argc, char *argv[])
129{
130	struct event		 ev_sigint, ev_sigterm, ev_sigchld, ev_sighup;
131	int			 ch, opts = 0;
132	int			 debug = 0;
133	int			 ipforwarding, mplsenable;
134	int			 mib[4];
135	size_t			 len;
136
137	conffile = CONF_FILE;
138	ldpd_process = PROC_MAIN;
139
140	log_init(1);	/* log to stderr until daemonized */
141
142	while ((ch = getopt(argc, argv, "dD:f:nv")) != -1) {
143		switch (ch) {
144		case 'd':
145			debug = 1;
146			break;
147		case 'D':
148			if (cmdline_symset(optarg) < 0)
149				log_warnx("could not parse macro definition %s",
150				    optarg);
151			break;
152		case 'f':
153			conffile = optarg;
154			break;
155		case 'n':
156			opts |= LDPD_OPT_NOACTION;
157			break;
158		case 'v':
159			if (opts & LDPD_OPT_VERBOSE)
160				opts |= LDPD_OPT_VERBOSE2;
161			opts |= LDPD_OPT_VERBOSE;
162			break;
163
164		default:
165			usage();
166			/* NOTREACHED */
167		}
168	}
169
170	mib[0] = CTL_NET;
171	mib[1] = PF_INET;
172	mib[2] = IPPROTO_IP;
173	mib[3] = IPCTL_FORWARDING;
174	len = sizeof(ipforwarding);
175	if (sysctl(mib, 4, &ipforwarding, &len, NULL, 0) == -1)
176		err(1, "sysctl");
177
178	if (ipforwarding != 1)
179		log_warnx("WARNING: IP forwarding NOT enabled");
180
181	mib[0] = CTL_NET;
182	mib[1] = PF_MPLS;
183	mib[2] = MPLSCTL_ENABLE;
184	len = sizeof(mplsenable);
185	if (sysctl(mib, 3, &mplsenable, &len, NULL, 0) == -1)
186		err(1, "sysctl");
187
188	if (mplsenable != 1)
189		log_warnx("WARNING: MPLS NOT enabled");
190
191	/* fetch interfaces early */
192	kif_init();
193
194	/* parse config file */
195	if ((ldpd_conf = parse_config(conffile, opts)) == NULL )
196		exit(1);
197
198	/* parse config file */
199
200	if (ldpd_conf->opts & LDPD_OPT_NOACTION) {
201		if (ldpd_conf->opts & LDPD_OPT_VERBOSE)
202			print_config(ldpd_conf);
203		else
204			fprintf(stderr, "configuration OK\n");
205		exit(0);
206	}
207
208	/* check for root privileges  */
209	if (geteuid())
210		errx(1, "need root privileges");
211
212	/* check for ldpd user */
213	if (getpwnam(LDPD_USER) == NULL)
214		errx(1, "unknown user %s", LDPD_USER);
215
216	log_init(debug);
217
218	if (!debug)
219		daemon(1, 0);
220
221	log_info("startup");
222
223	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC,
224	    pipe_parent2ldpe) == -1)
225		fatal("socketpair");
226	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_parent2lde) == -1)
227		fatal("socketpair");
228	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_ldpe2lde) == -1)
229		fatal("socketpair");
230	session_socket_blockmode(pipe_parent2ldpe[0], BM_NONBLOCK);
231	session_socket_blockmode(pipe_parent2ldpe[1], BM_NONBLOCK);
232	session_socket_blockmode(pipe_parent2lde[0], BM_NONBLOCK);
233	session_socket_blockmode(pipe_parent2lde[1], BM_NONBLOCK);
234	session_socket_blockmode(pipe_ldpe2lde[0], BM_NONBLOCK);
235	session_socket_blockmode(pipe_ldpe2lde[1], BM_NONBLOCK);
236
237	/* start children */
238	lde_pid = lde(ldpd_conf, pipe_parent2lde, pipe_ldpe2lde,
239	    pipe_parent2ldpe);
240	ldpe_pid = ldpe(ldpd_conf, pipe_parent2ldpe, pipe_ldpe2lde,
241	    pipe_parent2lde);
242
243	/* show who we are */
244	setproctitle("parent");
245
246	event_init();
247
248	/* setup signal handler */
249	signal_set(&ev_sigint, SIGINT, main_sig_handler, NULL);
250	signal_set(&ev_sigterm, SIGTERM, main_sig_handler, NULL);
251	signal_set(&ev_sigchld, SIGCHLD, main_sig_handler, NULL);
252	signal_set(&ev_sighup, SIGHUP, main_sig_handler, NULL);
253	signal_add(&ev_sigint, NULL);
254	signal_add(&ev_sigterm, NULL);
255	signal_add(&ev_sigchld, NULL);
256	signal_add(&ev_sighup, NULL);
257	signal(SIGPIPE, SIG_IGN);
258
259	/* setup pipes to children */
260	close(pipe_parent2ldpe[1]);
261	close(pipe_parent2lde[1]);
262	close(pipe_ldpe2lde[0]);
263	close(pipe_ldpe2lde[1]);
264
265	if ((iev_ldpe = malloc(sizeof(struct imsgev))) == NULL ||
266	    (iev_lde = malloc(sizeof(struct imsgev))) == NULL)
267		fatal(NULL);
268	imsg_init(&iev_ldpe->ibuf, pipe_parent2ldpe[0]);
269	iev_ldpe->handler = main_dispatch_ldpe;
270	imsg_init(&iev_lde->ibuf, pipe_parent2lde[0]);
271	iev_lde->handler = main_dispatch_lde;
272
273	/* setup event handler */
274	iev_ldpe->events = EV_READ;
275	event_set(&iev_ldpe->ev, iev_ldpe->ibuf.fd, iev_ldpe->events,
276	    iev_ldpe->handler, iev_ldpe);
277	event_add(&iev_ldpe->ev, NULL);
278
279	iev_lde->events = EV_READ;
280	event_set(&iev_lde->ev, iev_lde->ibuf.fd, iev_lde->events,
281	    iev_lde->handler, iev_lde);
282	event_add(&iev_lde->ev, NULL);
283
284	if (kr_init(!(ldpd_conf->flags & LDPD_FLAG_NO_LFIB_UPDATE)) == -1)
285		fatalx("kr_init failed");
286
287	/* remove unneded stuff from config */
288		/* ... */
289
290
291	event_dispatch();
292
293	ldpd_shutdown();
294	/* NOTREACHED */
295	return (0);
296}
297
298void
299ldpd_shutdown(void)
300{
301	pid_t		 pid;
302
303	if (ldpe_pid)
304		kill(ldpe_pid, SIGTERM);
305
306	if (lde_pid)
307		kill(lde_pid, SIGTERM);
308
309	control_cleanup();
310	kr_shutdown();
311
312	do {
313		if ((pid = wait(NULL)) == -1 &&
314		    errno != EINTR && errno != ECHILD)
315			fatal("wait");
316	} while (pid != -1 || (pid == -1 && errno == EINTR));
317
318	msgbuf_clear(&iev_ldpe->ibuf.w);
319	free(iev_ldpe);
320	msgbuf_clear(&iev_lde->ibuf.w);
321	free(iev_lde);
322	free(ldpd_conf);
323
324	close(ldpd_conf->ldp_session_socket);
325
326	log_info("terminating");
327	exit(0);
328}
329
330int
331check_child(pid_t pid, const char *pname)
332{
333	int	status;
334
335	if (waitpid(pid, &status, WNOHANG) > 0) {
336		if (WIFEXITED(status)) {
337			log_warnx("lost child: %s exited", pname);
338			return (1);
339		}
340		if (WIFSIGNALED(status)) {
341			log_warnx("lost child: %s terminated; signal %d",
342			    pname, WTERMSIG(status));
343			return (1);
344		}
345	}
346
347	return (0);
348}
349
350/* imsg handling */
351/* ARGSUSED */
352void
353main_dispatch_ldpe(int fd, short event, void *bula)
354{
355	struct imsgev		*iev = bula;
356	struct imsgbuf		*ibuf = &iev->ibuf;
357	struct imsg		 imsg;
358	ssize_t			 n;
359	int			 shut = 0;
360
361	if (event & EV_READ) {
362		if ((n = imsg_read(ibuf)) == -1)
363			fatal("imsg_read error");
364		if (n == 0)	/* connection closed */
365			shut = 1;
366	}
367	if (event & EV_WRITE) {
368		if (msgbuf_write(&ibuf->w) == -1)
369			fatal("msgbuf_write");
370	}
371
372	for (;;) {
373		if ((n = imsg_get(ibuf, &imsg)) == -1)
374			fatal("imsg_get");
375
376		if (n == 0)
377			break;
378
379		switch (imsg.hdr.type) {
380		case IMSG_CTL_RELOAD:
381/*
382			if (ldp_reload() == -1)
383				log_warnx("configuration reload failed");
384			else
385				log_debug("configuration reloaded");
386			break;
387*/
388		case IMSG_CTL_LFIB_COUPLE:
389			kr_lfib_couple();
390			break;
391		case IMSG_CTL_LFIB_DECOUPLE:
392			kr_lfib_decouple();
393			break;
394		case IMSG_CTL_KROUTE:
395		case IMSG_CTL_KROUTE_ADDR:
396			kr_show_route(&imsg);
397			break;
398		case IMSG_CTL_IFINFO:
399			if (imsg.hdr.len == IMSG_HEADER_SIZE)
400				kr_ifinfo(NULL, imsg.hdr.pid);
401			else if (imsg.hdr.len == IMSG_HEADER_SIZE + IFNAMSIZ)
402				kr_ifinfo(imsg.data, imsg.hdr.pid);
403			else
404				log_warnx("IFINFO request with wrong len");
405			break;
406		default:
407			log_debug("main_dispatch_ldpe: error handling imsg %d",
408			    imsg.hdr.type);
409			break;
410		}
411		imsg_free(&imsg);
412	}
413	if (!shut)
414		imsg_event_add(iev);
415	else {
416		/* this pipe is dead, so remove the event handler */
417		event_del(&iev->ev);
418		event_loopexit(NULL);
419	}
420}
421
422/* ARGSUSED */
423void
424main_dispatch_lde(int fd, short event, void *bula)
425{
426	struct imsgev  *iev = bula;
427	struct imsgbuf *ibuf = &iev->ibuf;
428	struct imsg	 imsg;
429	ssize_t		 n;
430	int		 shut = 0;
431
432	if (event & EV_READ) {
433		if ((n = imsg_read(ibuf)) == -1)
434			fatal("imsg_read error");
435		if (n == 0)	/* connection closed */
436			shut = 1;
437	}
438	if (event & EV_WRITE) {
439		if (msgbuf_write(&ibuf->w) == -1)
440			fatal("msgbuf_write");
441	}
442
443	for (;;) {
444		if ((n = imsg_get(ibuf, &imsg)) == -1)
445			fatal("imsg_get");
446
447		if (n == 0)
448			break;
449
450		switch (imsg.hdr.type) {
451		case IMSG_KLABEL_INSERT:
452			kroute_insert_label(imsg.data);
453			break;
454		case IMSG_KLABEL_CHANGE:
455			if (kr_change(imsg.data))
456				log_warn("main_dispatch_lde: error changing "
457				    "route");
458			break;
459		case IMSG_KLABEL_DELETE:
460			if (kr_delete(imsg.data))
461				log_warn("main_dispatch_lde: error deleting "
462				    "route");
463			break;
464		default:
465			log_debug("main_dispatch_lde: error handling imsg %d",
466			    imsg.hdr.type);
467			break;
468		}
469		imsg_free(&imsg);
470	}
471	if (!shut)
472		imsg_event_add(iev);
473	else {
474		/* this pipe is dead, so remove the event handler */
475		event_del(&iev->ev);
476		event_loopexit(NULL);
477	}
478}
479
480void
481main_imsg_compose_ldpe(int type, pid_t pid, void *data, u_int16_t datalen)
482{
483	imsg_compose_event(iev_ldpe, type, 0, pid, -1, data, datalen);
484}
485
486void
487main_imsg_compose_lde(int type, pid_t pid, void *data, u_int16_t datalen)
488{
489	imsg_compose_event(iev_lde, type, 0, pid, -1, data, datalen);
490}
491
492void
493imsg_event_add(struct imsgev *iev)
494{
495	iev->events = EV_READ;
496	if (iev->ibuf.w.queued)
497		iev->events |= EV_WRITE;
498
499	event_del(&iev->ev);
500	event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev);
501	event_add(&iev->ev, NULL);
502}
503
504int
505imsg_compose_event(struct imsgev *iev, u_int16_t type,
506    u_int32_t peerid, pid_t pid, int fd, void *data, u_int16_t datalen)
507{
508	int	ret;
509
510	if ((ret = imsg_compose(&iev->ibuf, type, peerid,
511	    pid, fd, data, datalen)) != -1)
512		imsg_event_add(iev);
513	return (ret);
514}
515
516/*
517int
518ldp_reload(void)
519{
520	struct lspace		*lspace;
521	struct iface		*iface;
522	struct ldpd_conf	*xconf;
523
524	if ((xconf = parse_config(conffile, ldpd_conf->opts)) == NULL)
525		return (-1);
526
527	if (ldp_sendboth(IMSG_RECONF_CONF, xconf, sizeof(*xconf)) == -1)
528		return (-1);
529
530	LIST_FOREACH(lspace, &xconf->lspace_list, entry) {
531		if (ldp_sendboth(IMSG_RECONF_AREA, lspace, sizeof(*lspace)) == -1)
532			return (-1);
533
534		LIST_FOREACH(iface, &lspace->iface_list, entry) {
535			if (ldp_sendboth(IMSG_RECONF_IFACE, iface,
536			    sizeof(*iface)) == -1)
537				return (-1);
538		}
539	}
540
541	if (ldp_sendboth(IMSG_RECONF_END, NULL, 0) == -1)
542		return (-1);
543
544	merge_config(ldpd_conf, xconf);
545
546	kr_reload();
547	return (0);
548}
549
550int
551ldp_sendboth(enum imsg_type type, void *buf, u_int16_t len)
552{
553	if (imsg_compose_event(iev_ldpe, type, 0, 0, -1, buf, len) == -1)
554		return (-1);
555	if (imsg_compose_event(iev_lde, type, 0, 0, -1, buf, len) == -1)
556		return (-1);
557	return (0);
558}
559
560void
561merge_config(struct ldpd_conf *conf, struct ldpd_conf *xconf)
562{
563	struct lspace		*a, *xa, *na;
564	struct iface		*iface;
565	struct redistribute	*r;
566	int			 rchange = 0;
567
568	conf->flags = xconf->flags;
569	conf->spf_delay = xconf->spf_delay;
570	conf->spf_hold_time = xconf->spf_hold_time;
571	if ((conf->redistribute & REDISTRIBUTE_ON) !=
572	    (xconf->redistribute & REDISTRIBUTE_ON))
573		rchange = 1;
574	conf->redistribute = xconf->redistribute;
575	conf->rfc1583compat = xconf->rfc1583compat;
576
577	if (ldpd_process == PROC_MAIN) {
578		while ((r = SIMPLEQ_FIRST(&conf->redist_list)) != NULL) {
579			SIMPLEQ_REMOVE_HEAD(&conf->redist_list, entry);
580			free(r);
581		}
582		while ((r = SIMPLEQ_FIRST(&xconf->redist_list)) != NULL) {
583			SIMPLEQ_REMOVE_HEAD(&xconf->redist_list, entry);
584			SIMPLEQ_INSERT_TAIL(&conf->redist_list, r, entry);
585		}
586		goto done;
587	}
588
589	for (a = LIST_FIRST(&conf->lspace_list); a != NULL; a = na) {
590		na = LIST_NEXT(a, entry);
591		if ((xa = lspace_find(xconf, a->id)) == NULL) {
592			if (ldpd_process == PROC_LDP_ENGINE) {
593				LIST_FOREACH(iface, &a->iface_list, entry)
594					if_fsm(iface, IF_EVT_DOWN);
595			}
596			LIST_REMOVE(a, entry);
597			lspace_del(a);
598		}
599	}
600
601	for (xa = LIST_FIRST(&xconf->lspace_list); xa != NULL; xa = na) {
602		na = LIST_NEXT(xa, entry);
603		if ((a = lspace_find(conf, xa->id)) == NULL) {
604			LIST_REMOVE(xa, entry);
605			LIST_INSERT_HEAD(&conf->lspace_list, xa, entry);
606			if (ldpd_process == PROC_LDP_ENGINE) {
607				LIST_FOREACH(iface, &xa->iface_list, entry) {
608					if_init(conf, iface);
609					if (if_fsm(iface, IF_EVT_UP)) {
610						log_debug("error starting "
611						    "interface %s",
612						    iface->name);
613					}
614				}
615			}
616			continue;
617		}
618		a->stub = xa->stub;
619		a->stub_default_cost = xa->stub_default_cost;
620		if (ldpd_process == PROC_LDE_ENGINE)
621			a->dirty = 1;
622
623		if (merge_interfaces(a, xa) &&
624		    ldpd_process == PROC_LDP_ENGINE)
625			a->dirty = 1;
626	}
627
628	if (ldpd_process == PROC_LDP_ENGINE) {
629		LIST_FOREACH(a, &conf->lspace_list, entry) {
630			LIST_FOREACH(iface, &a->iface_list, entry) {
631				if (iface->state == IF_STA_NEW) {
632					iface->state = IF_STA_DOWN;
633					if_init(conf, iface);
634					if (if_fsm(iface, IF_EVT_UP)) {
635						log_debug("error starting "
636						    "interface %s",
637						    iface->name);
638					}
639				}
640			}
641		}
642	}
643
644done:
645	while ((a = LIST_FIRST(&xconf->lspace_list)) != NULL) {
646		LIST_REMOVE(a, entry);
647		lspace_del(a);
648	}
649	free(xconf);
650}
651
652int
653merge_interfaces(struct lspace *a, struct lspace *xa)
654{
655	struct iface	*i, *xi, *ni;
656	int		 dirty = 0;
657
658	for (i = LIST_FIRST(&a->iface_list); i != NULL; i = ni) {
659		ni = LIST_NEXT(i, entry);
660		if (iface_lookup(xa, i) == NULL) {
661			log_debug("merge_config: proc %d label space %s removing "
662			    "interface %s", ldpd_process, inet_ntoa(a->id),
663			    i->name);
664			if (ldpd_process == PROC_LDP_ENGINE)
665				if_fsm(i, IF_EVT_DOWN);
666			LIST_REMOVE(i, entry);
667			if_del(i);
668		}
669	}
670
671	for (xi = LIST_FIRST(&xa->iface_list); xi != NULL; xi = ni) {
672		ni = LIST_NEXT(xi, entry);
673		if ((i = iface_lookup(a, xi)) == NULL) {
674			log_debug("merge_config: proc %d label space %s adding "
675			    "interface %s", ldpd_process, inet_ntoa(a->id),
676			    xi->name);
677			LIST_REMOVE(xi, entry);
678			LIST_INSERT_HEAD(&a->iface_list, xi, entry);
679			xi->lspace = a;
680			if (ldpd_process == PROC_LDP_ENGINE)
681				xi->state = IF_STA_NEW;
682			continue;
683		}
684		log_debug("merge_config: proc %d label space %s merging interface %s",
685		    ldpd_process, inet_ntoa(a->id), i->name);
686		i->addr = xi->addr;
687		i->dst = xi->dst;
688		i->mask = xi->mask;
689		i->abr_id = xi->abr_id;
690		i->baudrate = xi->baudrate;
691		i->dead_interval = xi->dead_interval;
692		i->mtu = xi->mtu;
693		i->transmit_delay = xi->transmit_delay;
694		i->hello_interval = xi->hello_interval;
695		i->rxmt_interval = xi->rxmt_interval;
696		if (i->metric != xi->metric)
697			dirty = 1;
698		i->metric = xi->metric;
699		i->priority = xi->priority;
700		i->flags = xi->flags;
701		i->type = xi->type;
702		i->media_type = xi->media_type;
703		i->linkstate = xi->linkstate;
704
705		if (i->passive != xi->passive) {
706			if (ldpd_process == PROC_LDP_ENGINE)
707				if_fsm(i, IF_EVT_DOWN);
708			i->passive = xi->passive;
709			if (ldpd_process == PROC_LDP_ENGINE)
710				if_fsm(i, IF_EVT_UP);
711		}
712	}
713	return (dirty);
714}
715
716struct iface *
717iface_lookup(struct lspace *lspace, struct iface *iface)
718{
719	struct iface	*i;
720
721	LIST_FOREACH(i, &lspace->iface_list, entry)
722		if (i->ifindex == iface->ifindex)
723			return (i);
724	return (NULL);
725}
726*/
727