xref: /openbsd-src/usr.sbin/ldpd/ldpe.c (revision 4c1e55dc91edd6e69ccc60ce855900fbc12cf34f)
1 /*	$OpenBSD: ldpe.c,v 1.16 2012/04/12 17:33:43 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 	accept_init();
164 
165 	/* setup signal handler */
166 	signal_set(&ev_sigint, SIGINT, ldpe_sig_handler, NULL);
167 	signal_set(&ev_sigterm, SIGTERM, ldpe_sig_handler, NULL);
168 	signal_add(&ev_sigint, NULL);
169 	signal_add(&ev_sigterm, NULL);
170 	signal(SIGPIPE, SIG_IGN);
171 	signal(SIGHUP, SIG_IGN);
172 
173 	/* setup pipes */
174 	close(pipe_parent2ldpe[0]);
175 	close(pipe_ldpe2lde[1]);
176 	close(pipe_parent2lde[0]);
177 	close(pipe_parent2lde[1]);
178 
179 	if ((iev_lde = malloc(sizeof(struct imsgev))) == NULL ||
180 	    (iev_main = malloc(sizeof(struct imsgev))) == NULL)
181 		fatal(NULL);
182 	imsg_init(&iev_lde->ibuf, pipe_ldpe2lde[0]);
183 	iev_lde->handler = ldpe_dispatch_lde;
184 	imsg_init(&iev_main->ibuf, pipe_parent2ldpe[1]);
185 	iev_main->handler = ldpe_dispatch_main;
186 
187 	/* setup event handler */
188 	iev_lde->events = EV_READ;
189 	event_set(&iev_lde->ev, iev_lde->ibuf.fd, iev_lde->events,
190 	    iev_lde->handler, iev_lde);
191 	event_add(&iev_lde->ev, NULL);
192 
193 	iev_main->events = EV_READ;
194 	event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events,
195 	    iev_main->handler, iev_main);
196 	event_add(&iev_main->ev, NULL);
197 
198 	event_set(&leconf->disc_ev, leconf->ldp_discovery_socket,
199 	    EV_READ|EV_PERSIST, disc_recv_packet, leconf);
200 	event_add(&leconf->disc_ev, NULL);
201 
202 	accept_add(leconf->ldp_session_socket, session_accept, leconf);
203 	/* listen on ldpd control socket */
204 	TAILQ_INIT(&ctl_conns);
205 	control_listen();
206 
207 	if ((pkt_ptr = calloc(1, IBUF_READ_SIZE)) == NULL)
208 		fatal("ldpe");
209 
210 	/* start interfaces */
211 	LIST_FOREACH(iface, &leconf->iface_list, entry) {
212 		if_init(xconf, iface);
213 		if (if_fsm(iface, IF_EVT_UP)) {
214 			log_debug("error starting interface %s",
215 			    iface->name);
216 		}
217 	}
218 
219 	event_dispatch();
220 
221 	ldpe_shutdown();
222 	/* NOTREACHED */
223 	return (0);
224 }
225 
226 void
227 ldpe_shutdown(void)
228 {
229 	struct iface	*iface;
230 
231 	/* stop all interfaces */
232 	LIST_FOREACH(iface, &leconf->iface_list, entry) {
233 		if (if_fsm(iface, IF_EVT_DOWN)) {
234 			log_debug("error stopping interface %s",
235 			    iface->name);
236 		}
237 	}
238 
239 	close(leconf->ldp_discovery_socket);
240 
241 	/* clean up */
242 	msgbuf_write(&iev_lde->ibuf.w);
243 	msgbuf_clear(&iev_lde->ibuf.w);
244 	free(iev_lde);
245 	msgbuf_write(&iev_main->ibuf.w);
246 	msgbuf_clear(&iev_main->ibuf.w);
247 	free(iev_main);
248 	free(leconf);
249 	free(pkt_ptr);
250 
251 	log_info("ldp engine exiting");
252 	_exit(0);
253 }
254 
255 /* imesg */
256 int
257 ldpe_imsg_compose_parent(int type, pid_t pid, void *data, u_int16_t datalen)
258 {
259 	return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen));
260 }
261 
262 int
263 ldpe_imsg_compose_lde(int type, u_int32_t peerid, pid_t pid,
264     void *data, u_int16_t datalen)
265 {
266 	return (imsg_compose_event(iev_lde, type, peerid, pid, -1,
267 	    data, datalen));
268 }
269 
270 /* ARGSUSED */
271 void
272 ldpe_dispatch_main(int fd, short event, void *bula)
273 {
274 	struct imsg	 imsg;
275 	struct imsgev	*iev = bula;
276 	struct imsgbuf  *ibuf = &iev->ibuf;
277 	struct iface	*iface = NULL;
278 	struct kif	*kif;
279 	int		 n, link_new, link_old, shut = 0;
280 
281 	if (event & EV_READ) {
282 		if ((n = imsg_read(ibuf)) == -1)
283 			fatal("imsg_read error");
284 		if (n == 0)	/* connection closed */
285 			shut = 1;
286 	}
287 	if (event & EV_WRITE) {
288 		if (msgbuf_write(&ibuf->w) == -1)
289 			fatal("ldpe_dispatch_main: msgbuf_write");
290 	}
291 
292 	for (;;) {
293 		if ((n = imsg_get(ibuf, &imsg)) == -1)
294 			fatal("ldpe_dispatch_main: imsg_read error");
295 		if (n == 0)
296 			break;
297 
298 		switch (imsg.hdr.type) {
299 		case IMSG_IFINFO:
300 			if (imsg.hdr.len != IMSG_HEADER_SIZE +
301 			    sizeof(struct kif))
302 				fatalx("IFINFO imsg with wrong len");
303 			kif = imsg.data;
304 			link_new = (kif->flags & IFF_UP) &&
305 			    LINK_STATE_IS_UP(kif->link_state);
306 
307 			LIST_FOREACH(iface, &leconf->iface_list, entry) {
308 				if (kif->ifindex == iface->ifindex) {
309 					link_old = (iface->flags & IFF_UP) &&
310 					    LINK_STATE_IS_UP(iface->linkstate);
311 					iface->flags = kif->flags;
312 					iface->linkstate = kif->link_state;
313 
314 					if (link_new == link_old)
315 						continue;
316 					if (link_new) {
317 						if_fsm(iface, IF_EVT_UP);
318 						log_warnx("interface %s up",
319 						    iface->name);
320 						/* XXX: send address msg */
321 					} else {
322 						if_fsm(iface, IF_EVT_DOWN);
323 						log_warnx("interface %s down",
324 						    iface->name);
325 						/* XXX: send address withdraw
326 						   msg */
327 					}
328 				}
329 			}
330 			break;
331 		case IMSG_RECONF_CONF:
332 			break;
333 		case IMSG_RECONF_IFACE:
334 			break;
335 		case IMSG_RECONF_END:
336 			break;
337 		case IMSG_CTL_KROUTE:
338 		case IMSG_CTL_KROUTE_ADDR:
339 		case IMSG_CTL_IFINFO:
340 		case IMSG_CTL_END:
341 			control_imsg_relay(&imsg);
342 			break;
343 		default:
344 			log_debug("ldpe_dispatch_main: error handling imsg %d",
345 			    imsg.hdr.type);
346 			break;
347 		}
348 		imsg_free(&imsg);
349 	}
350 	if (!shut)
351 		imsg_event_add(iev);
352 	else {
353 		/* this pipe is dead, so remove the event handler */
354 		event_del(&iev->ev);
355 		event_loopexit(NULL);
356 	}
357 }
358 
359 /* ARGSUSED */
360 void
361 ldpe_dispatch_lde(int fd, short event, void *bula)
362 {
363 	struct imsgev		*iev = bula;
364 	struct imsgbuf		*ibuf = &iev->ibuf;
365 	struct imsg		 imsg;
366 	struct map		 map;
367 	struct notify_msg	 nm;
368 	int			 n, shut = 0;
369 	struct nbr		*nbr = NULL;
370 
371 	if (event & EV_READ) {
372 		if ((n = imsg_read(ibuf)) == -1)
373 			fatal("imsg_read error");
374 		if (n == 0)	/* connection closed */
375 			shut = 1;
376 	}
377 	if (event & EV_WRITE) {
378 		if (msgbuf_write(&ibuf->w) == -1)
379 			fatal("ldpe_dispatch_lde: msgbuf_write");
380 	}
381 
382 	for (;;) {
383 		if ((n = imsg_get(ibuf, &imsg)) == -1)
384 			fatal("ldpe_dispatch_lde: imsg_read error");
385 		if (n == 0)
386 			break;
387 
388 		switch (imsg.hdr.type) {
389 		case IMSG_MAPPING_ADD:
390 		case IMSG_RELEASE_ADD:
391 		case IMSG_REQUEST_ADD:
392 			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(map))
393 				fatalx("invalid size of map request");
394 			memcpy(&map, imsg.data, sizeof(map));
395 
396 			nbr = nbr_find_peerid(imsg.hdr.peerid);
397 			if (nbr == NULL) {
398 				log_debug("ldpe_dispatch_lde: cannot find "
399 				    "neighbor");
400 				return;
401 			}
402 
403 			switch (imsg.hdr.type) {
404 			case IMSG_MAPPING_ADD:
405 				nbr_mapping_add(nbr, &nbr->mapping_list, &map);
406 				break;
407 			case IMSG_RELEASE_ADD:
408 				nbr_mapping_add(nbr, &nbr->release_list, &map);
409 				break;
410 			case IMSG_REQUEST_ADD:
411 				nbr_mapping_add(nbr, &nbr->request_list, &map);
412 				break;
413 			}
414 			break;
415 		case IMSG_MAPPING_ADD_END:
416 		case IMSG_RELEASE_ADD_END:
417 		case IMSG_REQUEST_ADD_END:
418 			nbr = nbr_find_peerid(imsg.hdr.peerid);
419 			if (nbr == NULL) {
420 				log_debug("ldpe_dispatch_lde: cannot find "
421 				    "neighbor");
422 				return;
423 			}
424 
425 			switch (imsg.hdr.type) {
426 			case IMSG_MAPPING_ADD_END:
427 				send_labelmapping(nbr);
428 				break;
429 			case IMSG_RELEASE_ADD_END:
430 				send_labelrelease(nbr);
431 				break;
432 			case IMSG_REQUEST_ADD_END:
433 				send_labelrequest(nbr);
434 				break;
435 			}
436 			break;
437 		case IMSG_NOTIFICATION_SEND:
438 			if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(nm))
439 				fatalx("invalid size of OE request");
440 			memcpy(&nm, imsg.data, sizeof(nm));
441 
442 			nbr = nbr_find_peerid(imsg.hdr.peerid);
443 			if (nbr == NULL) {
444 				log_debug("ldpe_dispatch_lde: cannot find "
445 				    "neighbor");
446 				return;
447 			}
448 
449 			send_notification_nbr(nbr, nm.status,
450 			    htonl(nm.messageid), htonl(nm.type));
451 			break;
452 		case IMSG_CTL_END:
453 		case IMSG_CTL_SHOW_LIB:
454 			control_imsg_relay(&imsg);
455 			break;
456 		default:
457 			log_debug("ldpe_dispatch_lde: error handling imsg %d",
458 			    imsg.hdr.type);
459 			break;
460 		}
461 		imsg_free(&imsg);
462 	}
463 	if (!shut)
464 		imsg_event_add(iev);
465 	else {
466 		/* this pipe is dead, so remove the event handler */
467 		event_del(&iev->ev);
468 		event_loopexit(NULL);
469 	}
470 }
471 
472 u_int32_t
473 ldpe_router_id(void)
474 {
475 	return (leconf->rtr_id.s_addr);
476 }
477 
478 void
479 ldpe_iface_ctl(struct ctl_conn *c, unsigned int idx)
480 {
481 	struct iface		*iface;
482 	struct ctl_iface	*ictl;
483 
484 	LIST_FOREACH(iface, &leconf->iface_list, entry) {
485 		if (idx == 0 || idx == iface->ifindex) {
486 			ictl = if_to_ctl(iface);
487 			imsg_compose_event(&c->iev,
488 			     IMSG_CTL_SHOW_INTERFACE,
489 			    0, 0, -1, ictl, sizeof(struct ctl_iface));
490 		}
491 	}
492 }
493