xref: /openbsd-src/usr.sbin/ldpd/ldpe.c (revision 5054e3e78af0749a9bb00ba9a024b3ee2d90290f)
1 /*	$OpenBSD: ldpe.c,v 1.3 2009/06/06 08:09:43 pyr 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 <netinet/in.h>
25 #include <arpa/inet.h>
26 #include <net/if_types.h>
27 #include <stdlib.h>
28 #include <signal.h>
29 #include <string.h>
30 #include <fcntl.h>
31 #include <pwd.h>
32 #include <unistd.h>
33 #include <event.h>
34 #include <err.h>
35 #include <errno.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 
39 #include "ldp.h"
40 #include "ldpd.h"
41 #include "ldpe.h"
42 #include "lde.h"
43 #include "control.h"
44 #include "log.h"
45 
46 void	 ldpe_sig_handler(int, short, void *);
47 void	 ldpe_shutdown(void);
48 
49 void	 recv_packet(int, short, void *);
50 
51 struct ldpd_conf	*leconf = NULL, *nconf;
52 struct imsgev		*iev_main;
53 struct imsgev		*iev_lde;
54 int			 oe_nofib;
55 
56 /* ARGSUSED */
57 void
58 ldpe_sig_handler(int sig, short event, void *bula)
59 {
60 	switch (sig) {
61 	case SIGINT:
62 	case SIGTERM:
63 		ldpe_shutdown();
64 		/* NOTREACHED */
65 	default:
66 		fatalx("unexpected signal");
67 	}
68 }
69 
70 /* label distribution protocol engine */
71 pid_t
72 ldpe(struct ldpd_conf *xconf, int pipe_parent2ldpe[2], int pipe_ldpe2lde[2],
73     int pipe_parent2lde[2])
74 {
75 	struct iface		*iface;
76 	struct passwd		*pw;
77 	struct event		 ev_sigint, ev_sigterm;
78 	struct sockaddr_in	 disc_addr, sess_addr;
79 	pid_t			 pid;
80 
81 	switch (pid = fork()) {
82 	case -1:
83 		fatal("cannot fork");
84 	case 0:
85 		break;
86 	default:
87 		return (pid);
88 	}
89 
90 	/* create ldpd control socket outside chroot */
91 	if (control_init() == -1)
92 		fatalx("control socket setup failed");
93 
94 	/* create the discovery UDP socket */
95 	disc_addr.sin_family = AF_INET;
96 	disc_addr.sin_port = htons(LDP_PORT);
97 	disc_addr.sin_addr.s_addr = INADDR_ANY;
98 
99 	if ((xconf->ldp_discovery_socket = socket(AF_INET, SOCK_DGRAM,
100 	    IPPROTO_UDP)) == -1)
101 		fatal("error creating discovery socket");
102 
103 	if (bind(xconf->ldp_discovery_socket, (struct sockaddr *)&disc_addr,
104 	    sizeof(disc_addr)) == -1)
105 		fatal("error binding discovery socket");
106 
107 	/* set some defaults */
108 	if (if_set_mcast_ttl(xconf->ldp_discovery_socket,
109 	    IP_DEFAULT_MULTICAST_TTL) == -1)
110 		fatal("if_set_mcast_ttl");
111 	if (if_set_mcast_loop(xconf->ldp_discovery_socket) == -1)
112 		fatal("if_set_mcast_loop");
113 	if (if_set_tos(xconf->ldp_discovery_socket,
114 	    IPTOS_PREC_INTERNETCONTROL) == -1)
115 		fatal("if_set_tos");
116 	if (if_set_recvif(xconf->ldp_discovery_socket, 1) == -1)
117 		fatal("if_set_recvif");
118 	if_set_recvbuf(xconf->ldp_discovery_socket);
119 
120 	/* create the session TCP socket */
121 	sess_addr.sin_family = AF_INET;
122 	sess_addr.sin_port = htons(LDP_PORT);
123 	sess_addr.sin_addr.s_addr = INADDR_ANY;
124 
125 	if ((xconf->ldp_session_socket = socket(AF_INET, SOCK_STREAM,
126 	    IPPROTO_TCP)) == -1)
127 		fatal("error creating session socket");
128 
129 	if (bind(xconf->ldp_session_socket, (struct sockaddr *)&sess_addr,
130 	    sizeof(sess_addr)) == -1)
131 		fatal("error binding session socket");
132 
133 	if (listen(xconf->ldp_session_socket, LDP_BACKLOG) == -1)
134 		fatal("error in listen on session socket");
135 
136 	/* set some defaults */
137 	if (if_set_tos(xconf->ldp_session_socket,
138 	    IPTOS_PREC_INTERNETCONTROL) == -1)
139 		fatal("if_set_tos");
140 	if (if_set_reuse(xconf->ldp_session_socket, 1) == -1)
141 		fatal("if_set_reuse");
142 	if (if_set_nonblock(xconf->ldp_session_socket) == -1)
143 		fatal("if_set_nonblock");
144 
145 	leconf = xconf;
146 	if (leconf->flags & LDPD_FLAG_NO_LFIB_UPDATE)
147 		oe_nofib = 1;
148 
149 	if ((pw = getpwnam(LDPD_USER)) == NULL)
150 		fatal("getpwnam");
151 
152 	if (chroot(pw->pw_dir) == -1)
153 		fatal("chroot");
154 	if (chdir("/") == -1)
155 		fatal("chdir(\"/\")");
156 
157 	setproctitle("ldp engine");
158 	ldpd_process = PROC_LDP_ENGINE;
159 
160 	if (setgroups(1, &pw->pw_gid) ||
161 	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
162 	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
163 		fatal("can't drop privileges");
164 
165 	event_init();
166 	nbr_init(NBR_HASHSIZE);
167 
168 	/* setup signal handler */
169 	signal_set(&ev_sigint, SIGINT, ldpe_sig_handler, NULL);
170 	signal_set(&ev_sigterm, SIGTERM, ldpe_sig_handler, NULL);
171 	signal_add(&ev_sigint, NULL);
172 	signal_add(&ev_sigterm, NULL);
173 	signal(SIGPIPE, SIG_IGN);
174 	signal(SIGHUP, SIG_IGN);
175 
176 	/* setup pipes */
177 	close(pipe_parent2ldpe[0]);
178 	close(pipe_ldpe2lde[1]);
179 	close(pipe_parent2lde[0]);
180 	close(pipe_parent2lde[1]);
181 
182 	if ((iev_lde = malloc(sizeof(struct imsgev))) == NULL ||
183 	    (iev_main = malloc(sizeof(struct imsgev))) == NULL)
184 		fatal(NULL);
185 	imsg_init(&iev_lde->ibuf, pipe_ldpe2lde[0]);
186 	iev_lde->handler = ldpe_dispatch_lde;
187 	imsg_init(&iev_main->ibuf, pipe_parent2ldpe[1]);
188 	iev_main->handler = ldpe_dispatch_main;
189 
190 	/* setup event handler */
191 	iev_lde->events = EV_READ;
192 	event_set(&iev_lde->ev, iev_lde->ibuf.fd, iev_lde->events,
193 	    iev_lde->handler, iev_lde);
194 	event_add(&iev_lde->ev, NULL);
195 
196 	iev_main->events = EV_READ;
197 	event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events,
198 	    iev_main->handler, iev_main);
199 	event_add(&iev_main->ev, NULL);
200 
201 	event_set(&leconf->disc_ev, leconf->ldp_discovery_socket,
202 	    EV_READ|EV_PERSIST, disc_recv_packet, leconf);
203 	event_add(&leconf->disc_ev, NULL);
204 
205 	event_set(&leconf->sess_ev, leconf->ldp_session_socket,
206 	    EV_READ|EV_PERSIST, session_recv_packet, leconf);
207 	event_add(&leconf->sess_ev, NULL);
208 
209 	/* listen on ldpd control socket */
210 	TAILQ_INIT(&ctl_conns);
211 	control_listen();
212 
213 	if ((pkt_ptr = calloc(1, READ_BUF_SIZE)) == NULL)
214 		fatal("ldpe");
215 
216 	/* start interfaces */
217 	LIST_FOREACH(iface, &leconf->iface_list, entry) {
218 		if_init(xconf, iface);
219 		if (if_fsm(iface, IF_EVT_UP)) {
220 			log_debug("error starting interface %s",
221 			    iface->name);
222 		}
223 	}
224 
225 	event_dispatch();
226 
227 	ldpe_shutdown();
228 	/* NOTREACHED */
229 	return (0);
230 }
231 
232 void
233 ldpe_shutdown(void)
234 {
235 	struct iface	*iface;
236 
237 	/* stop all interfaces */
238 	LIST_FOREACH(iface, &leconf->iface_list, entry) {
239 		if (if_fsm(iface, IF_EVT_DOWN)) {
240 			log_debug("error stopping interface %s",
241 			    iface->name);
242 		}
243 	}
244 
245 	close(leconf->ldp_discovery_socket);
246 
247 	/* clean up */
248 	msgbuf_write(&iev_lde->ibuf.w);
249 	msgbuf_clear(&iev_lde->ibuf.w);
250 	free(iev_lde);
251 	msgbuf_write(&iev_main->ibuf.w);
252 	msgbuf_clear(&iev_main->ibuf.w);
253 	free(iev_main);
254 	free(leconf);
255 	free(pkt_ptr);
256 
257 	log_info("ldp engine exiting");
258 	_exit(0);
259 }
260 
261 /* imesg */
262 int
263 ldpe_imsg_compose_parent(int type, pid_t pid, void *data, u_int16_t datalen)
264 {
265 	return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen));
266 }
267 
268 int
269 ldpe_imsg_compose_lde(int type, u_int32_t peerid, pid_t pid,
270     void *data, u_int16_t datalen)
271 {
272 	return (imsg_compose_event(iev_lde, type, peerid, pid, -1,
273 	    data, datalen));
274 }
275 
276 /* ARGSUSED */
277 void
278 ldpe_dispatch_main(int fd, short event, void *bula)
279 {
280 	struct imsg	 imsg;
281 	struct imsgev	*iev = bula;
282 	struct imsgbuf  *ibuf = &iev->ibuf;
283 	struct iface	*iface = NULL;
284 	struct kif	*kif;
285 	int		 n, link_ok, shut = 0;
286 
287 	if (event & EV_READ) {
288 		if ((n = imsg_read(ibuf)) == -1)
289 			fatal("imsg_read error");
290 		if (n == 0)	/* connection closed */
291 			shut = 1;
292 	}
293 	if (event & EV_WRITE) {
294 		if (msgbuf_write(&ibuf->w) == -1)
295 			fatal("msgbuf_write");
296 	}
297 
298 	for (;;) {
299 		if ((n = imsg_get(ibuf, &imsg)) == -1)
300 			fatal("ldpe_dispatch_main: imsg_read error");
301 		if (n == 0)
302 			break;
303 
304 		switch (imsg.hdr.type) {
305 		case IMSG_IFINFO:
306 			if (imsg.hdr.len != IMSG_HEADER_SIZE +
307 			    sizeof(struct kif))
308 				fatalx("IFINFO imsg with wrong len");
309 			kif = imsg.data;
310 			link_ok = (kif->flags & IFF_UP) &&
311 			    (LINK_STATE_IS_UP(kif->link_state) ||
312 			    (kif->link_state == LINK_STATE_UNKNOWN &&
313 			    kif->media_type != IFT_CARP));
314 
315 			LIST_FOREACH(iface, &leconf->iface_list, entry) {
316 				if (kif->ifindex == iface->ifindex &&
317 				    iface->type != IF_TYPE_VIRTUALLINK) {
318 					iface->flags = kif->flags;
319 					iface->linkstate = kif->link_state;
320 
321 					if (link_ok) {
322 						if_fsm(iface, IF_EVT_UP);
323 						log_warnx("interface %s up",
324 						    iface->name);
325 						/* XXX: send address msg */
326 					} else {
327 						if_fsm(iface, IF_EVT_DOWN);
328 						log_warnx("interface %s down",
329 						    iface->name);
330 						/* XXX: send address withdraw
331 						   msg */
332 					}
333 				}
334 			}
335 			break;
336 		case IMSG_RECONF_CONF:
337 			break;
338 		case IMSG_RECONF_AREA:
339 			break;
340 		case IMSG_RECONF_IFACE:
341 			break;
342 		case IMSG_RECONF_END:
343 			break;
344 		case IMSG_CTL_KROUTE:
345 		case IMSG_CTL_KROUTE_ADDR:
346 		case IMSG_CTL_IFINFO:
347 		case IMSG_CTL_END:
348 			control_imsg_relay(&imsg);
349 			break;
350 		default:
351 			log_debug("ldpe_dispatch_main: error handling imsg %d",
352 			    imsg.hdr.type);
353 			break;
354 		}
355 		imsg_free(&imsg);
356 	}
357 	if (!shut)
358 		imsg_event_add(iev);
359 	else {
360 		/* this pipe is dead, so remove the event handler */
361 		event_del(&iev->ev);
362 		event_loopexit(NULL);
363 	}
364 }
365 
366 /* ARGSUSED */
367 void
368 ldpe_dispatch_lde(int fd, short event, void *bula)
369 {
370 	struct imsgev		*iev = bula;
371 	struct imsgbuf		*ibuf = &iev->ibuf;
372 	struct imsg		 imsg;
373 	struct map		 map;
374 	struct notify_msg	 nm;
375 	int			 n, shut = 0;
376 	struct nbr		*nbr = NULL;
377 
378 	if (event & EV_READ) {
379 		if ((n = imsg_read(ibuf)) == -1)
380 			fatal("imsg_read error");
381 		if (n == 0)	/* connection closed */
382 			shut = 1;
383 	}
384 	if (event & EV_WRITE) {
385 		if (msgbuf_write(&ibuf->w) == -1)
386 			fatal("msgbuf_write");
387 	}
388 
389 	for (;;) {
390 		if ((n = imsg_get(ibuf, &imsg)) == -1)
391 			fatal("ldpe_dispatch_lde: imsg_read error");
392 		if (n == 0)
393 			break;
394 
395 		switch (imsg.hdr.type) {
396 		case IMSG_MAPPING_ADD:
397 			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(map))
398 				fatalx("invalid size of OE request");
399 			memcpy(&map, imsg.data, sizeof(map));
400 
401 			nbr = nbr_find_peerid(imsg.hdr.peerid);
402 			if (nbr == NULL) {
403 				log_debug("ldpe_dispatch_lde: cannot find "
404 				    "neighbor");
405 				return;
406 			}
407 
408 			nbr_mapping_add(nbr, &nbr->mapping_list, &map);
409 			break;
410 		case IMSG_MAPPING_ADD_END:
411 			nbr = nbr_find_peerid(imsg.hdr.peerid);
412 			if (nbr == NULL) {
413 				log_debug("ldpe_dispatch_lde: cannot find "
414 				    "neighbor");
415 				return;
416 			}
417 
418 			send_labelmapping(nbr);
419 			break;
420 		case IMSG_RELEASE_ADD:
421 			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(map))
422 				fatalx("invalid size of OE request");
423 			memcpy(&map, imsg.data, sizeof(map));
424 
425 			nbr = nbr_find_peerid(imsg.hdr.peerid);
426 			if (nbr == NULL) {
427 				log_debug("ldpe_dispatch_lde: cannot find "
428 				    "neighbor");
429 				return;
430 			}
431 
432 			nbr_mapping_add(nbr, &nbr->release_list, &map);
433 			break;
434 		case IMSG_RELEASE_ADD_END:
435 			nbr = nbr_find_peerid(imsg.hdr.peerid);
436 			if (nbr == NULL) {
437 				log_debug("ldpe_dispatch_lde: cannot find "
438 				    "neighbor");
439 				return;
440 			}
441 			send_labelrelease(nbr);
442 			break;
443 		case IMSG_NOTIFICATION_SEND:
444 			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(nm))
445 				fatalx("invalid size of OE request");
446 			memcpy(&nm, imsg.data, sizeof(nm));
447 
448 			nbr = nbr_find_peerid(imsg.hdr.peerid);
449 			if (nbr == NULL) {
450 				log_debug("ldpe_dispatch_lde: cannot find "
451 				    "neighbor");
452 				return;
453 			}
454 
455 			send_notification_nbr(nbr, nm.status,
456 			    htonl(nm.messageid), htonl(nm.type));
457 			break;
458 		case IMSG_REQUEST_ADD:
459 			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(map))
460 				fatalx("invalid size of OE request");
461 			memcpy(&map, imsg.data, sizeof(map));
462 
463 			nbr = nbr_find_peerid(imsg.hdr.peerid);
464 			if (nbr == NULL) {
465 				log_debug("ldpe_dispatch_lde: cannot find "
466 				    "neighbor");
467 				return;
468 			}
469 
470 			nbr_mapping_add(nbr, &nbr->request_list, &map);
471 			break;
472 		case IMSG_REQUEST_ADD_END:
473 			nbr = nbr_find_peerid(imsg.hdr.peerid);
474 			if (nbr == NULL) {
475 				log_debug("ldpe_dispatch_lde: cannot find "
476 				    "neighbor");
477 				return;
478 			}
479 			send_labelrequest(nbr);
480 			break;
481 		case IMSG_CTL_END:
482 		case IMSG_CTL_SHOW_LIB:
483 			control_imsg_relay(&imsg);
484 			break;
485 		default:
486 			log_debug("ldpe_dispatch_lde: error handling imsg %d",
487 			    imsg.hdr.type);
488 			break;
489 		}
490 		imsg_free(&imsg);
491 	}
492 	if (!shut)
493 		imsg_event_add(iev);
494 	else {
495 		/* this pipe is dead, so remove the event handler */
496 		event_del(&iev->ev);
497 		event_loopexit(NULL);
498 	}
499 }
500 
501 u_int32_t
502 ldpe_router_id(void)
503 {
504 	return (leconf->rtr_id.s_addr);
505 }
506 
507 void
508 ldpe_fib_update(int type)
509 {
510 	if (type == IMSG_CTL_LFIB_COUPLE)
511 		oe_nofib = 0;
512 	if (type == IMSG_CTL_LFIB_DECOUPLE)
513 		oe_nofib = 1;
514 }
515 
516 void
517 ldpe_iface_ctl(struct ctl_conn *c, unsigned int idx)
518 {
519 	struct iface		*iface;
520 	struct ctl_iface	*ictl;
521 
522 	LIST_FOREACH(iface, &leconf->iface_list, entry) {
523 		if (idx == 0 || idx == iface->ifindex) {
524 			ictl = if_to_ctl(iface);
525 			imsg_compose_event(&c->iev,
526 			     IMSG_CTL_SHOW_INTERFACE,
527 			    0, 0, -1, ictl, sizeof(struct ctl_iface));
528 		}
529 	}
530 }
531 
532 void
533 ldpe_nbr_ctl(struct ctl_conn *c)
534 {
535 	struct iface	*iface;
536 	struct nbr	*nbr;
537 	struct ctl_nbr	*nctl;
538 
539 	LIST_FOREACH(iface, &leconf->iface_list, entry) {
540 		LIST_FOREACH(nbr, &iface->nbr_list, entry) {
541 			if (iface->self != nbr) {
542 				nctl = nbr_to_ctl(nbr);
543 				imsg_compose_event(&c->iev,
544 				    IMSG_CTL_SHOW_NBR, 0, 0, -1, nctl,
545 				    sizeof(struct ctl_nbr));
546 			}
547 		}
548 	}
549 
550 	imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
551 }
552