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