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