1 /* $OpenBSD: ripd.c,v 1.13 2009/03/27 14:37:25 michele Exp $ */ 2 3 /* 4 * Copyright (c) 2006 Michele Marchetto <mydecay@openbeer.it> 5 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> 6 * Copyright (c) 2004 Esben Norby <norby@openbsd.org> 7 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> 8 * 9 * Permission to use, copy, modify, and distribute this software for any 10 * purpose with or without fee is hereby granted, provided that the above 11 * copyright notice and this permission notice appear in all copies. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 */ 21 22 #include <sys/types.h> 23 #include <sys/socket.h> 24 #include <sys/queue.h> 25 #include <sys/time.h> 26 #include <sys/stat.h> 27 #include <sys/wait.h> 28 #include <sys/param.h> 29 #include <sys/sysctl.h> 30 31 #include <netinet/in.h> 32 #include <arpa/inet.h> 33 34 #include <event.h> 35 #include <err.h> 36 #include <errno.h> 37 #include <pwd.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <signal.h> 42 #include <unistd.h> 43 44 #include "rip.h" 45 #include "ripd.h" 46 #include "ripe.h" 47 #include "log.h" 48 #include "control.h" 49 #include "rde.h" 50 51 __dead void usage(void); 52 int check_child(pid_t, const char *); 53 void main_sig_handler(int, short, void *); 54 void ripd_shutdown(void); 55 void main_dispatch_ripe(int, short, void *); 56 void main_dispatch_rde(int, short, void *); 57 58 int pipe_parent2ripe[2]; 59 int pipe_parent2rde[2]; 60 int pipe_ripe2rde[2]; 61 62 struct ripd_conf *conf = NULL; 63 struct imsgbuf *ibuf_ripe; 64 struct imsgbuf *ibuf_rde; 65 66 pid_t ripe_pid = 0; 67 pid_t rde_pid = 0; 68 69 __dead void 70 usage(void) 71 { 72 extern char *__progname; 73 74 fprintf(stderr, "usage: %s [-dnv] [-D macro=value] [-f file]\n", 75 __progname); 76 exit(1); 77 } 78 79 /* ARGSUSED */ 80 void 81 main_sig_handler(int sig, short event, void *arg) 82 { 83 /* 84 * signal handler rules don't apply, libevent decouples for us 85 */ 86 87 int die = 0; 88 89 switch (sig) { 90 case SIGTERM: 91 case SIGINT: 92 die = 1; 93 /* FALLTHROUGH */ 94 case SIGCHLD: 95 if (check_child(ripe_pid, "rip engine")) { 96 ripe_pid = 0; 97 die = 1; 98 } 99 if (check_child(rde_pid, "route decision engine")) { 100 rde_pid = 0; 101 die = 1; 102 } 103 if (die) 104 ripd_shutdown(); 105 break; 106 case SIGHUP: 107 /* reconfigure */ 108 /* ... */ 109 break; 110 default: 111 fatalx("unexpected signal"); 112 /* NOTREACHED */ 113 } 114 } 115 116 int 117 main(int argc, char *argv[]) 118 { 119 struct event ev_sigint, ev_sigterm, ev_sigchld, ev_sighup; 120 int mib[4]; 121 int debug = 0; 122 int ipforwarding; 123 int ch; 124 int opts = 0; 125 char *conffile; 126 size_t len; 127 128 conffile = CONF_FILE; 129 ripd_process = PROC_MAIN; 130 131 log_init(1); /* log to stderr until daemonized */ 132 133 while ((ch = getopt(argc, argv, "cdD:f:nv")) != -1) { 134 switch (ch) { 135 case 'c': 136 opts |= RIPD_OPT_FORCE_DEMOTE; 137 break; 138 case 'd': 139 debug = 1; 140 break; 141 case 'D': 142 if (cmdline_symset(optarg) < 0) 143 log_warnx("could not parse macro definition %s", 144 optarg); 145 break; 146 case 'f': 147 conffile = optarg; 148 break; 149 case 'n': 150 opts |= RIPD_OPT_NOACTION; 151 break; 152 case 'v': 153 if (opts & RIPD_OPT_VERBOSE) 154 opts |= RIPD_OPT_VERBOSE2; 155 opts |= RIPD_OPT_VERBOSE; 156 break; 157 default: 158 usage(); 159 /* NOTREACHED */ 160 } 161 } 162 163 argc -= optind; 164 argv += optind; 165 if (argc > 0) 166 usage(); 167 168 mib[0] = CTL_NET; 169 mib[1] = PF_INET; 170 mib[2] = IPPROTO_IP; 171 mib[3] = IPCTL_FORWARDING; 172 len = sizeof(ipforwarding); 173 if (sysctl(mib, 4, &ipforwarding, &len, NULL, 0) == -1) 174 err(1, "sysctl"); 175 176 if (!ipforwarding) 177 log_warnx("WARNING: IP forwarding NOT enabled"); 178 179 /* fetch interfaces early */ 180 kif_init(); 181 182 /* parse config file */ 183 if ((conf = parse_config(conffile, opts)) == NULL ) 184 exit(1); 185 186 if (conf->opts & RIPD_OPT_NOACTION) { 187 if (conf->opts & RIPD_OPT_VERBOSE) 188 print_config(conf); 189 else 190 fprintf(stderr, "configuration OK\n"); 191 exit(0); 192 } 193 194 /* check for root privileges */ 195 if (geteuid()) 196 errx(1, "need root privileges"); 197 198 /* check for ripd user */ 199 if (getpwnam(RIPD_USER) == NULL) 200 errx(1, "unknown user %s", RIPD_USER); 201 202 log_init(debug); 203 204 if (!debug) 205 daemon(1, 0); 206 207 log_info("startup"); 208 209 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, 210 pipe_parent2ripe) == -1) 211 fatal("socketpair"); 212 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_parent2rde) == -1) 213 fatal("socketpair"); 214 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_ripe2rde) == -1) 215 fatal("socketpair"); 216 session_socket_blockmode(pipe_parent2ripe[0], BM_NONBLOCK); 217 session_socket_blockmode(pipe_parent2ripe[1], BM_NONBLOCK); 218 session_socket_blockmode(pipe_parent2rde[0], BM_NONBLOCK); 219 session_socket_blockmode(pipe_parent2rde[1], BM_NONBLOCK); 220 session_socket_blockmode(pipe_ripe2rde[0], BM_NONBLOCK); 221 session_socket_blockmode(pipe_ripe2rde[1], BM_NONBLOCK); 222 223 /* start children */ 224 rde_pid = rde(conf, pipe_parent2rde, pipe_ripe2rde, pipe_parent2ripe); 225 ripe_pid = ripe(conf, pipe_parent2ripe, pipe_ripe2rde, pipe_parent2rde); 226 227 /* show who we are */ 228 setproctitle("parent"); 229 230 event_init(); 231 232 /* setup signal handler */ 233 signal_set(&ev_sigint, SIGINT, main_sig_handler, NULL); 234 signal_set(&ev_sigterm, SIGTERM, main_sig_handler, NULL); 235 signal_set(&ev_sigchld, SIGINT, main_sig_handler, NULL); 236 signal_set(&ev_sighup, SIGHUP, main_sig_handler, NULL); 237 signal_add(&ev_sigint, NULL); 238 signal_add(&ev_sigterm, NULL); 239 signal_add(&ev_sigchld, NULL); 240 signal_add(&ev_sighup, NULL); 241 signal(SIGPIPE, SIG_IGN); 242 243 /* setup pipes to children */ 244 close(pipe_parent2ripe[1]); 245 close(pipe_parent2rde[1]); 246 close(pipe_ripe2rde[0]); 247 close(pipe_ripe2rde[1]); 248 249 if ((ibuf_ripe = malloc(sizeof(struct imsgbuf))) == NULL || 250 (ibuf_rde = malloc(sizeof(struct imsgbuf))) == NULL) 251 fatal(NULL); 252 imsg_init(ibuf_ripe, pipe_parent2ripe[0], main_dispatch_ripe); 253 imsg_init(ibuf_rde, pipe_parent2rde[0], main_dispatch_rde); 254 255 /* setup event handler */ 256 ibuf_ripe->events = EV_READ; 257 event_set(&ibuf_ripe->ev, ibuf_ripe->fd, ibuf_ripe->events, 258 ibuf_ripe->handler, ibuf_ripe); 259 event_add(&ibuf_ripe->ev, NULL); 260 261 ibuf_rde->events = EV_READ; 262 event_set(&ibuf_rde->ev, ibuf_rde->fd, ibuf_rde->events, 263 ibuf_rde->handler, ibuf_rde); 264 event_add(&ibuf_rde->ev, NULL); 265 266 if (kr_init(!(conf->flags & RIPD_FLAG_NO_FIB_UPDATE)) == -1) 267 fatalx("kr_init failed"); 268 269 event_dispatch(); 270 271 ripd_shutdown(); 272 /* NOTREACHED */ 273 return (0); 274 } 275 276 void 277 ripd_shutdown(void) 278 { 279 struct iface *i; 280 pid_t pid; 281 282 if (ripe_pid) 283 kill(ripe_pid, SIGTERM); 284 285 if (rde_pid) 286 kill(rde_pid, SIGTERM); 287 288 while ((i = LIST_FIRST(&conf->iface_list)) != NULL) { 289 LIST_REMOVE(i, entry); 290 if_del(i); 291 } 292 293 control_cleanup(); 294 kr_shutdown(); 295 296 do { 297 if ((pid = wait(NULL)) == -1 && 298 errno != EINTR && errno != ECHILD) 299 fatal("wait"); 300 } while (pid != -1 || (pid == -1 && errno == EINTR)); 301 302 msgbuf_clear(&ibuf_ripe->w); 303 free(ibuf_ripe); 304 msgbuf_clear(&ibuf_rde->w); 305 free(ibuf_rde); 306 free(conf); 307 308 log_info("terminating"); 309 exit(0); 310 } 311 312 int 313 check_child(pid_t pid, const char *pname) 314 { 315 int status; 316 317 if (waitpid(pid, &status, WNOHANG) > 0) { 318 if (WIFEXITED(status)) { 319 log_warnx("lost child: %s exited", pname); 320 return (1); 321 } 322 if (WIFSIGNALED(status)) { 323 log_warnx("lost child: %s terminated; signal %d", 324 pname, WTERMSIG(status)); 325 return (1); 326 } 327 } 328 329 return (0); 330 } 331 332 /* imsg handling */ 333 /* ARGSUSED */ 334 void 335 main_dispatch_ripe(int fd, short event, void *bula) 336 { 337 struct imsgbuf *ibuf = bula; 338 struct imsg imsg; 339 struct demote_msg dmsg; 340 ssize_t n; 341 int shut = 0; 342 343 switch (event) { 344 case EV_READ: 345 if ((n = imsg_read(ibuf)) == -1) 346 fatal("imsg_read error"); 347 if (n == 0) /* connection closed */ 348 shut = 1; 349 break; 350 case EV_WRITE: 351 if (msgbuf_write(&ibuf->w) == -1) 352 fatal("msgbuf_write"); 353 imsg_event_add(ibuf); 354 return; 355 default: 356 fatalx("unknown event"); 357 } 358 359 for (;;) { 360 if ((n = imsg_get(ibuf, &imsg)) == -1) 361 fatal("imsg_get"); 362 363 if (n == 0) 364 break; 365 366 switch (imsg.hdr.type) { 367 case IMSG_CTL_RELOAD: 368 /* XXX reconfig */ 369 break; 370 case IMSG_CTL_FIB_COUPLE: 371 kr_fib_couple(); 372 break; 373 case IMSG_CTL_FIB_DECOUPLE: 374 kr_fib_decouple(); 375 break; 376 case IMSG_CTL_KROUTE: 377 case IMSG_CTL_KROUTE_ADDR: 378 kr_show_route(&imsg); 379 break; 380 case IMSG_CTL_IFINFO: 381 if (imsg.hdr.len == IMSG_HEADER_SIZE) 382 kr_ifinfo(NULL, imsg.hdr.pid); 383 else if (imsg.hdr.len == IMSG_HEADER_SIZE + IFNAMSIZ) 384 kr_ifinfo(imsg.data, imsg.hdr.pid); 385 else 386 log_warnx("IFINFO request with wrong len"); 387 break; 388 case IMSG_DEMOTE: 389 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(dmsg)) 390 fatalx("invalid size of OE request"); 391 memcpy(&dmsg, imsg.data, sizeof(dmsg)); 392 carp_demote_set(dmsg.demote_group, dmsg.level); 393 break; 394 default: 395 log_debug("main_dispatch_ripe: error handling imsg %d", 396 imsg.hdr.type); 397 break; 398 } 399 imsg_free(&imsg); 400 } 401 if (!shut) 402 imsg_event_add(ibuf); 403 else { 404 /* this pipe is dead, so remove the event handler */ 405 event_del(&ibuf->ev); 406 event_loopexit(NULL); 407 } 408 } 409 410 /* ARGSUSED */ 411 void 412 main_dispatch_rde(int fd, short event, void *bula) 413 { 414 struct imsgbuf *ibuf = bula; 415 struct imsg imsg; 416 ssize_t n; 417 int shut = 0; 418 419 switch (event) { 420 case EV_READ: 421 if ((n = imsg_read(ibuf)) == -1) 422 fatal("imsg_read error"); 423 if (n == 0) /* connection closed */ 424 shut = 1; 425 break; 426 case EV_WRITE: 427 if (msgbuf_write(&ibuf->w) == -1) 428 fatal("msgbuf_write"); 429 imsg_event_add(ibuf); 430 return; 431 default: 432 fatalx("unknown event"); 433 } 434 435 for (;;) { 436 if ((n = imsg_get(ibuf, &imsg)) == -1) 437 fatal("imsg_get"); 438 439 if (n == 0) 440 break; 441 442 switch (imsg.hdr.type) { 443 case IMSG_KROUTE_CHANGE: 444 if (kr_change(imsg.data)) 445 log_warn("main_dispatch_rde: error changing " 446 "route"); 447 break; 448 case IMSG_KROUTE_DELETE: 449 if (kr_delete(imsg.data)) 450 log_warn("main_dispatch_rde: error deleting " 451 "route"); 452 break; 453 default: 454 log_debug("main_dispatch_rde: error handling imsg %d", 455 imsg.hdr.type); 456 break; 457 } 458 imsg_free(&imsg); 459 } 460 if (!shut) 461 imsg_event_add(ibuf); 462 else { 463 /* this pipe is dead, so remove the event handler */ 464 event_del(&ibuf->ev); 465 event_loopexit(NULL); 466 } 467 } 468 469 void 470 main_imsg_compose_ripe(int type, pid_t pid, void *data, u_int16_t datalen) 471 { 472 imsg_compose(ibuf_ripe, type, 0, pid, data, datalen); 473 } 474 475 void 476 main_imsg_compose_rde(int type, pid_t pid, void *data, u_int16_t datalen) 477 { 478 imsg_compose(ibuf_rde, type, 0, pid, data, datalen); 479 } 480 481 int 482 rip_redistribute(struct kroute *kr) 483 { 484 struct redistribute *r; 485 u_int8_t is_default = 0; 486 487 if (kr->flags & F_RIPD_INSERTED) 488 return (1); 489 490 /* only allow 0.0.0.0/0 via REDIST_DEFAULT */ 491 if (kr->prefix.s_addr == INADDR_ANY && kr->netmask.s_addr == INADDR_ANY) 492 is_default = 1; 493 494 SIMPLEQ_FOREACH(r, &conf->redist_list, entry) { 495 switch (r->type & ~REDIST_NO) { 496 case REDIST_LABEL: 497 if (kr->rtlabel == r->label) 498 return (r->type & REDIST_NO ? 0 : 1); 499 break; 500 case REDIST_STATIC: 501 /* 502 * Dynamic routes are not redistributable. Placed here 503 * so that link local addresses can be redistributed 504 * via a rtlabel. 505 */ 506 if (is_default) 507 continue; 508 if (kr->flags & F_DYNAMIC) 509 continue; 510 if (kr->flags & F_STATIC) 511 return (r->type & REDIST_NO ? 0 : 1); 512 break; 513 case REDIST_CONNECTED: 514 if (is_default) 515 continue; 516 if (kr->flags & F_DYNAMIC) 517 continue; 518 if (kr->flags & F_CONNECTED) 519 return (r->type & REDIST_NO ? 0 : 1); 520 break; 521 case REDIST_ADDR: 522 if (kr->flags & F_DYNAMIC) 523 continue; 524 525 if (r->addr.s_addr == INADDR_ANY && 526 r->mask.s_addr == INADDR_ANY) { 527 if (is_default) 528 return (r->type & REDIST_NO? 0 : 1); 529 else 530 return (0); 531 } 532 533 if ((kr->prefix.s_addr & r->mask.s_addr) == 534 (r->addr.s_addr & r->mask.s_addr) && 535 (kr->netmask.s_addr & r->mask.s_addr) == 536 r->mask.s_addr) 537 return (r->type & REDIST_NO? 0 : 1); 538 break; 539 case REDIST_DEFAULT: 540 if (is_default) 541 return (r->type & REDIST_NO? 0 : 1); 542 break; 543 } 544 } 545 546 return (0); 547 } 548 549 /* this needs to be added here so that ripctl can be used without libevent */ 550 void 551 imsg_event_add(struct imsgbuf *ibuf) 552 { 553 ibuf->events = EV_READ; 554 if (ibuf->w.queued) 555 ibuf->events |= EV_WRITE; 556 557 event_del(&ibuf->ev); 558 event_set(&ibuf->ev, ibuf->fd, ibuf->events, ibuf->handler, ibuf); 559 event_add(&ibuf->ev, NULL); 560 } 561