xref: /openbsd-src/usr.sbin/ldpd/ldpe.c (revision 50b7afb2c2c0993b0894d4e34bf857cb13ed9c80)
1 /*	$OpenBSD: ldpe.c,v 1.24 2014/07/12 20:16:38 krw 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 extern struct nbr_id_head	nbrs_by_id;
47 RB_PROTOTYPE(nbr_id_head, nbr, id_tree, nbr_id_compare)
48 
49 void	 ldpe_sig_handler(int, short, void *);
50 void	 ldpe_shutdown(void);
51 
52 struct ldpd_conf	*leconf = NULL, *nconf;
53 struct imsgev		*iev_main;
54 struct imsgev		*iev_lde;
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 tnbr		*tnbr;
77 	struct passwd		*pw;
78 	struct event		 ev_sigint, ev_sigterm;
79 	struct sockaddr_in	 disc_addr, sess_addr;
80 	pid_t			 pid;
81 
82 	switch (pid = fork()) {
83 	case -1:
84 		fatal("cannot fork");
85 	case 0:
86 		break;
87 	default:
88 		return (pid);
89 	}
90 
91 	leconf = xconf;
92 
93 	setproctitle("ldp engine");
94 	ldpd_process = PROC_LDP_ENGINE;
95 
96 	/* create ldpd control socket outside chroot */
97 	if (control_init() == -1)
98 		fatalx("control socket setup failed");
99 
100 	/* create the discovery UDP socket */
101 	disc_addr.sin_family = AF_INET;
102 	disc_addr.sin_port = htons(LDP_PORT);
103 	disc_addr.sin_addr.s_addr = INADDR_ANY;
104 
105 	if ((xconf->ldp_discovery_socket = socket(AF_INET, SOCK_DGRAM,
106 	    IPPROTO_UDP)) == -1)
107 		fatal("error creating discovery socket");
108 
109 	if (if_set_reuse(xconf->ldp_discovery_socket, 1) == -1)
110 		fatal("if_set_reuse");
111 
112 	if (bind(xconf->ldp_discovery_socket, (struct sockaddr *)&disc_addr,
113 	    sizeof(disc_addr)) == -1)
114 		fatal("error binding discovery socket");
115 
116 	/* set some defaults */
117 	if (if_set_mcast_ttl(xconf->ldp_discovery_socket,
118 	    IP_DEFAULT_MULTICAST_TTL) == -1)
119 		fatal("if_set_mcast_ttl");
120 	if (if_set_mcast_loop(xconf->ldp_discovery_socket) == -1)
121 		fatal("if_set_mcast_loop");
122 	if (if_set_tos(xconf->ldp_discovery_socket,
123 	    IPTOS_PREC_INTERNETCONTROL) == -1)
124 		fatal("if_set_tos");
125 	if (if_set_recvif(xconf->ldp_discovery_socket, 1) == -1)
126 		fatal("if_set_recvif");
127 	if_set_recvbuf(xconf->ldp_discovery_socket);
128 
129 	/* create the extended discovery UDP socket */
130 	disc_addr.sin_family = AF_INET;
131 	disc_addr.sin_port = htons(LDP_PORT);
132 	disc_addr.sin_addr.s_addr = xconf->rtr_id.s_addr;
133 
134 	if ((xconf->ldp_ediscovery_socket = socket(AF_INET, SOCK_DGRAM,
135 	    IPPROTO_UDP)) == -1)
136 		fatal("error creating extended discovery socket");
137 
138 	if (if_set_reuse(xconf->ldp_ediscovery_socket, 1) == -1)
139 		fatal("if_set_reuse");
140 
141 	if (bind(xconf->ldp_ediscovery_socket, (struct sockaddr *)&disc_addr,
142 	    sizeof(disc_addr)) == -1)
143 		fatal("error binding extended discovery socket");
144 
145 	/* set some defaults */
146 	if (if_set_tos(xconf->ldp_ediscovery_socket,
147 	    IPTOS_PREC_INTERNETCONTROL) == -1)
148 		fatal("if_set_tos");
149 	if (if_set_recvif(xconf->ldp_ediscovery_socket, 1) == -1)
150 		fatal("if_set_recvif");
151 	if_set_recvbuf(xconf->ldp_ediscovery_socket);
152 
153 	/* create the session TCP socket */
154 	sess_addr.sin_family = AF_INET;
155 	sess_addr.sin_port = htons(LDP_PORT);
156 	sess_addr.sin_addr.s_addr = INADDR_ANY;
157 
158 	if ((xconf->ldp_session_socket = socket(AF_INET, SOCK_STREAM,
159 	    IPPROTO_TCP)) == -1)
160 		fatal("error creating session socket");
161 
162 	if (if_set_reuse(xconf->ldp_session_socket, 1) == -1)
163 		fatal("if_set_reuse");
164 
165 	if (bind(xconf->ldp_session_socket, (struct sockaddr *)&sess_addr,
166 	    sizeof(sess_addr)) == -1)
167 		fatal("error binding session socket");
168 
169 	if (listen(xconf->ldp_session_socket, LDP_BACKLOG) == -1)
170 		fatal("error in listen on session socket");
171 
172 	/* set some defaults */
173 	if (if_set_tos(xconf->ldp_session_socket,
174 	    IPTOS_PREC_INTERNETCONTROL) == -1)
175 		fatal("if_set_tos");
176 	session_socket_blockmode(xconf->ldp_session_socket, BM_NONBLOCK);
177 
178 	if ((pw = getpwnam(LDPD_USER)) == NULL)
179 		fatal("getpwnam");
180 
181 	if (chroot(pw->pw_dir) == -1)
182 		fatal("chroot");
183 	if (chdir("/") == -1)
184 		fatal("chdir(\"/\")");
185 
186 	if (setgroups(1, &pw->pw_gid) ||
187 	    setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
188 	    setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
189 		fatal("can't drop privileges");
190 
191 	event_init();
192 	accept_init();
193 
194 	/* setup signal handler */
195 	signal_set(&ev_sigint, SIGINT, ldpe_sig_handler, NULL);
196 	signal_set(&ev_sigterm, SIGTERM, ldpe_sig_handler, NULL);
197 	signal_add(&ev_sigint, NULL);
198 	signal_add(&ev_sigterm, NULL);
199 	signal(SIGPIPE, SIG_IGN);
200 	signal(SIGHUP, SIG_IGN);
201 
202 	/* setup pipes */
203 	close(pipe_parent2ldpe[0]);
204 	close(pipe_ldpe2lde[1]);
205 	close(pipe_parent2lde[0]);
206 	close(pipe_parent2lde[1]);
207 
208 	if ((iev_lde = malloc(sizeof(struct imsgev))) == NULL ||
209 	    (iev_main = malloc(sizeof(struct imsgev))) == NULL)
210 		fatal(NULL);
211 	imsg_init(&iev_lde->ibuf, pipe_ldpe2lde[0]);
212 	iev_lde->handler = ldpe_dispatch_lde;
213 	imsg_init(&iev_main->ibuf, pipe_parent2ldpe[1]);
214 	iev_main->handler = ldpe_dispatch_main;
215 
216 	/* setup event handler */
217 	iev_lde->events = EV_READ;
218 	event_set(&iev_lde->ev, iev_lde->ibuf.fd, iev_lde->events,
219 	    iev_lde->handler, iev_lde);
220 	event_add(&iev_lde->ev, NULL);
221 
222 	iev_main->events = EV_READ;
223 	event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events,
224 	    iev_main->handler, iev_main);
225 	event_add(&iev_main->ev, NULL);
226 
227 	event_set(&leconf->disc_ev, leconf->ldp_discovery_socket,
228 	    EV_READ|EV_PERSIST, disc_recv_packet, NULL);
229 	event_add(&leconf->disc_ev, NULL);
230 
231 	event_set(&leconf->edisc_ev, leconf->ldp_ediscovery_socket,
232 	    EV_READ|EV_PERSIST, disc_recv_packet, NULL);
233 	event_add(&leconf->edisc_ev, NULL);
234 
235 	accept_add(leconf->ldp_session_socket, session_accept, NULL);
236 	/* listen on ldpd control socket */
237 	TAILQ_INIT(&ctl_conns);
238 	control_listen();
239 
240 	if ((pkt_ptr = calloc(1, IBUF_READ_SIZE)) == NULL)
241 		fatal("ldpe");
242 
243 	/* initialize interfaces */
244 	LIST_FOREACH(iface, &leconf->iface_list, entry)
245 		if_init(xconf, iface);
246 
247 	/* start configured targeted neighbors */
248 	LIST_FOREACH(tnbr, &leconf->tnbr_list, entry)
249 		tnbr_init(xconf, tnbr);
250 
251 	event_dispatch();
252 
253 	ldpe_shutdown();
254 	/* NOTREACHED */
255 	return (0);
256 }
257 
258 void
259 ldpe_shutdown(void)
260 {
261 	struct iface	*iface;
262 	struct tnbr	*tnbr;
263 
264 	/* stop all interfaces */
265 	while ((iface = LIST_FIRST(&leconf->iface_list)) != NULL) {
266 		if (if_fsm(iface, IF_EVT_DOWN)) {
267 			log_debug("error stopping interface %s",
268 			    iface->name);
269 		}
270 		LIST_REMOVE(iface, entry);
271 		if_del(iface);
272 	}
273 
274 	/* stop all targeted neighbors */
275 	while ((tnbr = LIST_FIRST(&leconf->tnbr_list)) != NULL) {
276 		LIST_REMOVE(tnbr, entry);
277 		tnbr_del(tnbr);
278 	}
279 
280 	close(leconf->ldp_discovery_socket);
281 	close(leconf->ldp_session_socket);
282 
283 	/* clean up */
284 	msgbuf_write(&iev_lde->ibuf.w);
285 	msgbuf_clear(&iev_lde->ibuf.w);
286 	free(iev_lde);
287 	msgbuf_write(&iev_main->ibuf.w);
288 	msgbuf_clear(&iev_main->ibuf.w);
289 	free(iev_main);
290 	free(leconf);
291 	free(pkt_ptr);
292 
293 	log_info("ldp engine exiting");
294 	_exit(0);
295 }
296 
297 /* imesg */
298 int
299 ldpe_imsg_compose_parent(int type, pid_t pid, void *data, u_int16_t datalen)
300 {
301 	return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen));
302 }
303 
304 int
305 ldpe_imsg_compose_lde(int type, u_int32_t peerid, pid_t pid,
306     void *data, u_int16_t datalen)
307 {
308 	return (imsg_compose_event(iev_lde, type, peerid, pid, -1,
309 	    data, datalen));
310 }
311 
312 /* ARGSUSED */
313 void
314 ldpe_dispatch_main(int fd, short event, void *bula)
315 {
316 	struct imsg	 imsg;
317 	struct imsgev	*iev = bula;
318 	struct imsgbuf  *ibuf = &iev->ibuf;
319 	struct iface	*iface = NULL;
320 	struct if_addr	*if_addr = NULL, *a;
321 	struct kif	*kif;
322 	struct kaddr	*kaddr;
323 	int		 n, shut = 0;
324 	struct nbr	*nbr;
325 
326 	if (event & EV_READ) {
327 		if ((n = imsg_read(ibuf)) == -1)
328 			fatal("imsg_read error");
329 		if (n == 0)	/* connection closed */
330 			shut = 1;
331 	}
332 	if (event & EV_WRITE) {
333 		if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
334 			fatal("ldpe_dispatch_main: msgbuf_write");
335 		if (n == 0)
336 			shut = 1;
337 	}
338 
339 	for (;;) {
340 		if ((n = imsg_get(ibuf, &imsg)) == -1)
341 			fatal("ldpe_dispatch_main: imsg_read error");
342 		if (n == 0)
343 			break;
344 
345 		switch (imsg.hdr.type) {
346 		case IMSG_IFSTATUS:
347 		case IMSG_IFUP:
348 		case IMSG_IFDOWN:
349 			if (imsg.hdr.len != IMSG_HEADER_SIZE +
350 			    sizeof(struct kif))
351 				fatalx("IFINFO imsg with wrong len");
352 
353 			kif = imsg.data;
354 			iface = if_lookup(kif->ifindex);
355 			if (!iface)
356 				break;
357 
358 			iface->flags = kif->flags;
359 			iface->linkstate = kif->link_state;
360 			switch (imsg.hdr.type) {
361 			case IMSG_IFUP:
362 				if_fsm(iface, IF_EVT_UP);
363 				break;
364 			case IMSG_IFDOWN:
365 				if_fsm(iface, IF_EVT_DOWN);
366 				break;
367 			default:
368 				break;
369 			}
370 			break;
371 		case IMSG_NEWADDR:
372 			if (imsg.hdr.len != IMSG_HEADER_SIZE +
373 			    sizeof(struct kaddr))
374 				fatalx("NEWADDR imsg with wrong len");
375 			kaddr = imsg.data;
376 
377 			if ((if_addr = calloc(1, sizeof(*if_addr))) == NULL)
378 				fatal("ldpe_dispatch_main");
379 
380 			if_addr->addr.s_addr = kaddr->addr.s_addr;
381 			if_addr->mask.s_addr = kaddr->mask.s_addr;
382 			if_addr->dstbrd.s_addr = kaddr->dstbrd.s_addr;
383 
384 			LIST_INSERT_HEAD(&leconf->addr_list, if_addr,
385 			    global_entry);
386 			RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
387 				if (nbr->state != NBR_STA_OPER)
388 					continue;
389 				send_address(nbr, if_addr);
390 			}
391 
392 			iface = if_lookup(kaddr->ifindex);
393 			if (iface) {
394 				LIST_INSERT_HEAD(&iface->addr_list, if_addr,
395 				    iface_entry);
396 				if_fsm(iface, IF_EVT_NEWADDR);
397 			}
398 			break;
399 		case IMSG_DELADDR:
400 			if (imsg.hdr.len != IMSG_HEADER_SIZE +
401 			    sizeof(struct kaddr))
402 				fatalx("DELADDR imsg with wrong len");
403 			kaddr = imsg.data;
404 
405 			LIST_FOREACH(a, &leconf->addr_list, global_entry)
406 				if (a->addr.s_addr == kaddr->addr.s_addr &&
407 				    a->mask.s_addr == kaddr->mask.s_addr &&
408 				    a->dstbrd.s_addr == kaddr->dstbrd.s_addr)
409 					break;
410 			if_addr = a;
411 			if (!if_addr)
412 				break;
413 
414 			LIST_REMOVE(if_addr, global_entry);
415 			RB_FOREACH(nbr, nbr_id_head, &nbrs_by_id) {
416 				if (nbr->state != NBR_STA_OPER)
417 					continue;
418 				send_address_withdraw(nbr, if_addr);
419 			}
420 
421 			iface = if_lookup(kaddr->ifindex);
422 			if (iface) {
423 				LIST_REMOVE(if_addr, iface_entry);
424 				if_fsm(iface, IF_EVT_DELADDR);
425 			}
426 			free(if_addr);
427 			break;
428 		case IMSG_RECONF_CONF:
429 			break;
430 		case IMSG_RECONF_IFACE:
431 			break;
432 		case IMSG_RECONF_END:
433 			break;
434 		case IMSG_CTL_KROUTE:
435 		case IMSG_CTL_KROUTE_ADDR:
436 		case IMSG_CTL_IFINFO:
437 		case IMSG_CTL_END:
438 			control_imsg_relay(&imsg);
439 			break;
440 		default:
441 			log_debug("ldpe_dispatch_main: error handling imsg %d",
442 			    imsg.hdr.type);
443 			break;
444 		}
445 		imsg_free(&imsg);
446 	}
447 	if (!shut)
448 		imsg_event_add(iev);
449 	else {
450 		/* this pipe is dead, so remove the event handler */
451 		event_del(&iev->ev);
452 		event_loopexit(NULL);
453 	}
454 }
455 
456 /* ARGSUSED */
457 void
458 ldpe_dispatch_lde(int fd, short event, void *bula)
459 {
460 	struct imsgev		*iev = bula;
461 	struct imsgbuf		*ibuf = &iev->ibuf;
462 	struct imsg		 imsg;
463 	struct map		 map;
464 	struct notify_msg	 nm;
465 	int			 n, shut = 0;
466 	struct nbr		*nbr = NULL;
467 
468 	if (event & EV_READ) {
469 		if ((n = imsg_read(ibuf)) == -1)
470 			fatal("imsg_read error");
471 		if (n == 0)	/* connection closed */
472 			shut = 1;
473 	}
474 	if (event & EV_WRITE) {
475 		if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
476 			fatal("ldpe_dispatch_lde: msgbuf_write");
477 		if (n == 0)
478 			shut = 1;
479 	}
480 
481 	for (;;) {
482 		if ((n = imsg_get(ibuf, &imsg)) == -1)
483 			fatal("ldpe_dispatch_lde: imsg_read error");
484 		if (n == 0)
485 			break;
486 
487 		switch (imsg.hdr.type) {
488 		case IMSG_MAPPING_ADD:
489 		case IMSG_RELEASE_ADD:
490 		case IMSG_REQUEST_ADD:
491 			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(map))
492 				fatalx("invalid size of map request");
493 			memcpy(&map, imsg.data, sizeof(map));
494 
495 			nbr = nbr_find_peerid(imsg.hdr.peerid);
496 			if (nbr == NULL) {
497 				log_debug("ldpe_dispatch_lde: cannot find "
498 				    "neighbor");
499 				return;
500 			}
501 			if (nbr->state != NBR_STA_OPER)
502 				return;
503 
504 			switch (imsg.hdr.type) {
505 			case IMSG_MAPPING_ADD:
506 				nbr_mapping_add(nbr, &nbr->mapping_list, &map);
507 				break;
508 			case IMSG_RELEASE_ADD:
509 				nbr_mapping_add(nbr, &nbr->release_list, &map);
510 				break;
511 			case IMSG_REQUEST_ADD:
512 				nbr_mapping_add(nbr, &nbr->request_list, &map);
513 				break;
514 			}
515 			break;
516 		case IMSG_MAPPING_ADD_END:
517 		case IMSG_RELEASE_ADD_END:
518 		case IMSG_REQUEST_ADD_END:
519 			nbr = nbr_find_peerid(imsg.hdr.peerid);
520 			if (nbr == NULL) {
521 				log_debug("ldpe_dispatch_lde: cannot find "
522 				    "neighbor");
523 				return;
524 			}
525 			if (nbr->state != NBR_STA_OPER)
526 				return;
527 
528 			switch (imsg.hdr.type) {
529 			case IMSG_MAPPING_ADD_END:
530 				send_labelmessage(nbr, MSG_TYPE_LABELMAPPING,
531 				    &nbr->mapping_list);
532 				break;
533 			case IMSG_RELEASE_ADD_END:
534 				send_labelmessage(nbr, MSG_TYPE_LABELRELEASE,
535 				    &nbr->release_list);
536 				break;
537 			case IMSG_REQUEST_ADD_END:
538 				send_labelmessage(nbr, MSG_TYPE_LABELREQUEST,
539 				    &nbr->request_list);
540 				break;
541 			}
542 			break;
543 		case IMSG_NOTIFICATION_SEND:
544 			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(nm))
545 				fatalx("invalid size of OE request");
546 			memcpy(&nm, imsg.data, sizeof(nm));
547 
548 			nbr = nbr_find_peerid(imsg.hdr.peerid);
549 			if (nbr == NULL) {
550 				log_debug("ldpe_dispatch_lde: cannot find "
551 				    "neighbor");
552 				return;
553 			}
554 			if (nbr->state != NBR_STA_OPER)
555 				return;
556 
557 			send_notification_nbr(nbr, nm.status,
558 			    htonl(nm.messageid), htonl(nm.type));
559 			break;
560 		case IMSG_CTL_END:
561 		case IMSG_CTL_SHOW_LIB:
562 			control_imsg_relay(&imsg);
563 			break;
564 		default:
565 			log_debug("ldpe_dispatch_lde: error handling imsg %d",
566 			    imsg.hdr.type);
567 			break;
568 		}
569 		imsg_free(&imsg);
570 	}
571 	if (!shut)
572 		imsg_event_add(iev);
573 	else {
574 		/* this pipe is dead, so remove the event handler */
575 		event_del(&iev->ev);
576 		event_loopexit(NULL);
577 	}
578 }
579 
580 u_int32_t
581 ldpe_router_id(void)
582 {
583 	return (leconf->rtr_id.s_addr);
584 }
585 
586 void
587 ldpe_iface_ctl(struct ctl_conn *c, unsigned int idx)
588 {
589 	struct iface		*iface;
590 	struct ctl_iface	*ictl;
591 
592 	LIST_FOREACH(iface, &leconf->iface_list, entry) {
593 		if (idx == 0 || idx == iface->ifindex) {
594 			ictl = if_to_ctl(iface);
595 			imsg_compose_event(&c->iev,
596 			     IMSG_CTL_SHOW_INTERFACE,
597 			    0, 0, -1, ictl, sizeof(struct ctl_iface));
598 		}
599 	}
600 }
601