1 /* $OpenBSD: engine.c,v 1.18 2021/01/19 16:54:48 florian Exp $ */ 2 3 /* 4 * Copyright (c) 2018 Florian Obser <florian@openbsd.org> 5 * Copyright (c) 2004, 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/queue.h> 24 #include <sys/socket.h> 25 #include <sys/syslog.h> 26 #include <sys/uio.h> 27 28 #include <netinet/in.h> 29 #include <net/if.h> 30 #include <arpa/inet.h> 31 #include <netinet/icmp6.h> 32 33 #include <errno.h> 34 #include <event.h> 35 #include <imsg.h> 36 #include <signal.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <pwd.h> 40 #include <unistd.h> 41 42 #include "log.h" 43 #include "rad.h" 44 #include "engine.h" 45 46 struct engine_iface { 47 TAILQ_ENTRY(engine_iface) entry; 48 struct event timer; 49 uint32_t if_index; 50 }; 51 52 TAILQ_HEAD(, engine_iface) engine_interfaces; 53 54 55 __dead void engine_shutdown(void); 56 void engine_sig_handler(int sig, short, void *); 57 void engine_dispatch_frontend(int, short, void *); 58 void engine_dispatch_main(int, short, void *); 59 void parse_ra_rs(struct imsg_ra_rs *); 60 void parse_ra(struct imsg_ra_rs *); 61 void parse_rs(struct imsg_ra_rs *); 62 void update_iface(uint32_t); 63 void remove_iface(uint32_t); 64 struct engine_iface *find_engine_iface_by_id(uint32_t); 65 void iface_timeout(int, short, void *); 66 67 struct rad_conf *engine_conf; 68 static struct imsgev *iev_frontend; 69 static struct imsgev *iev_main; 70 struct sockaddr_in6 all_nodes; 71 72 void 73 engine_sig_handler(int sig, short event, void *arg) 74 { 75 /* 76 * Normal signal handler rules don't apply because libevent 77 * decouples for us. 78 */ 79 80 switch (sig) { 81 case SIGINT: 82 case SIGTERM: 83 engine_shutdown(); 84 default: 85 fatalx("unexpected signal"); 86 } 87 } 88 89 void 90 engine(int debug, int verbose) 91 { 92 struct event ev_sigint, ev_sigterm; 93 struct passwd *pw; 94 95 engine_conf = config_new_empty(); 96 97 log_init(debug, LOG_DAEMON); 98 log_setverbose(verbose); 99 100 if ((pw = getpwnam(RAD_USER)) == NULL) 101 fatal("getpwnam"); 102 103 if (chroot(pw->pw_dir) == -1) 104 fatal("chroot"); 105 if (chdir("/") == -1) 106 fatal("chdir(\"/\")"); 107 108 setproctitle("%s", "engine"); 109 log_procinit("engine"); 110 111 if (setgroups(1, &pw->pw_gid) || 112 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 113 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 114 fatal("can't drop privileges"); 115 116 if (pledge("stdio recvfd", NULL) == -1) 117 fatal("pledge"); 118 119 event_init(); 120 121 /* Setup signal handler(s). */ 122 signal_set(&ev_sigint, SIGINT, engine_sig_handler, NULL); 123 signal_set(&ev_sigterm, SIGTERM, engine_sig_handler, NULL); 124 signal_add(&ev_sigint, NULL); 125 signal_add(&ev_sigterm, NULL); 126 signal(SIGPIPE, SIG_IGN); 127 signal(SIGHUP, SIG_IGN); 128 129 /* Setup pipe and event handler to the main process. */ 130 if ((iev_main = malloc(sizeof(struct imsgev))) == NULL) 131 fatal(NULL); 132 133 imsg_init(&iev_main->ibuf, 3); 134 iev_main->handler = engine_dispatch_main; 135 136 /* Setup event handlers. */ 137 iev_main->events = EV_READ; 138 event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events, 139 iev_main->handler, iev_main); 140 event_add(&iev_main->ev, NULL); 141 142 all_nodes.sin6_len = sizeof(all_nodes); 143 all_nodes.sin6_family = AF_INET6; 144 if (inet_pton(AF_INET6, "ff02::1", &all_nodes.sin6_addr) != 1) 145 fatal("inet_pton"); 146 147 TAILQ_INIT(&engine_interfaces); 148 149 event_dispatch(); 150 151 engine_shutdown(); 152 } 153 154 __dead void 155 engine_shutdown(void) 156 { 157 /* Close pipes. */ 158 msgbuf_clear(&iev_frontend->ibuf.w); 159 close(iev_frontend->ibuf.fd); 160 msgbuf_clear(&iev_main->ibuf.w); 161 close(iev_main->ibuf.fd); 162 163 config_clear(engine_conf); 164 165 free(iev_frontend); 166 free(iev_main); 167 168 log_info("engine exiting"); 169 exit(0); 170 } 171 172 int 173 engine_imsg_compose_frontend(int type, pid_t pid, void *data, uint16_t datalen) 174 { 175 return (imsg_compose_event(iev_frontend, type, 0, pid, -1, 176 data, datalen)); 177 } 178 179 void 180 engine_dispatch_frontend(int fd, short event, void *bula) 181 { 182 struct imsgev *iev = bula; 183 struct imsgbuf *ibuf; 184 struct imsg imsg; 185 struct imsg_ra_rs ra_rs; 186 ssize_t n; 187 uint32_t if_index; 188 int shut = 0, verbose; 189 190 ibuf = &iev->ibuf; 191 192 if (event & EV_READ) { 193 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 194 fatal("imsg_read error"); 195 if (n == 0) /* Connection closed. */ 196 shut = 1; 197 } 198 if (event & EV_WRITE) { 199 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 200 fatal("msgbuf_write"); 201 if (n == 0) /* Connection closed. */ 202 shut = 1; 203 } 204 205 for (;;) { 206 if ((n = imsg_get(ibuf, &imsg)) == -1) 207 fatal("%s: imsg_get error", __func__); 208 if (n == 0) /* No more messages. */ 209 break; 210 211 switch (imsg.hdr.type) { 212 case IMSG_RA_RS: 213 if (IMSG_DATA_SIZE(imsg) != sizeof(ra_rs)) 214 fatalx("%s: IMSG_RA_RS wrong length: %lu", 215 __func__, IMSG_DATA_SIZE(imsg)); 216 memcpy(&ra_rs, imsg.data, sizeof(ra_rs)); 217 parse_ra_rs(&ra_rs); 218 break; 219 case IMSG_UPDATE_IF: 220 if (IMSG_DATA_SIZE(imsg) != sizeof(if_index)) 221 fatalx("%s: IMSG_UPDATE_IF wrong length: %lu", 222 __func__, IMSG_DATA_SIZE(imsg)); 223 memcpy(&if_index, imsg.data, sizeof(if_index)); 224 update_iface(if_index); 225 break; 226 case IMSG_REMOVE_IF: 227 if (IMSG_DATA_SIZE(imsg) != sizeof(if_index)) 228 fatalx("%s: IMSG_REMOVE_IF wrong length: %lu", 229 __func__, IMSG_DATA_SIZE(imsg)); 230 memcpy(&if_index, imsg.data, sizeof(if_index)); 231 remove_iface(if_index); 232 break; 233 case IMSG_CTL_LOG_VERBOSE: 234 if (IMSG_DATA_SIZE(imsg) != sizeof(verbose)) 235 fatalx("%s: IMSG_CTL_LOG_VERBOSE wrong length: " 236 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 237 memcpy(&verbose, imsg.data, sizeof(verbose)); 238 log_setverbose(verbose); 239 break; 240 default: 241 log_debug("%s: unexpected imsg %d", __func__, 242 imsg.hdr.type); 243 break; 244 } 245 imsg_free(&imsg); 246 } 247 if (!shut) 248 imsg_event_add(iev); 249 else { 250 /* This pipe is dead. Remove its event handler. */ 251 event_del(&iev->ev); 252 event_loopexit(NULL); 253 } 254 } 255 256 void 257 engine_dispatch_main(int fd, short event, void *bula) 258 { 259 static struct rad_conf *nconf; 260 static struct ra_iface_conf *ra_iface_conf; 261 static struct ra_options_conf *ra_options; 262 struct imsg imsg; 263 struct imsgev *iev = bula; 264 struct imsgbuf *ibuf; 265 struct ra_prefix_conf *ra_prefix_conf; 266 struct ra_rdnss_conf *ra_rdnss_conf; 267 struct ra_dnssl_conf *ra_dnssl_conf; 268 ssize_t n; 269 int shut = 0; 270 271 ibuf = &iev->ibuf; 272 273 if (event & EV_READ) { 274 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 275 fatal("imsg_read error"); 276 if (n == 0) /* Connection closed. */ 277 shut = 1; 278 } 279 if (event & EV_WRITE) { 280 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 281 fatal("msgbuf_write"); 282 if (n == 0) /* Connection closed. */ 283 shut = 1; 284 } 285 286 for (;;) { 287 if ((n = imsg_get(ibuf, &imsg)) == -1) 288 fatal("%s: imsg_get error", __func__); 289 if (n == 0) /* No more messages. */ 290 break; 291 292 switch (imsg.hdr.type) { 293 case IMSG_SOCKET_IPC: 294 /* 295 * Setup pipe and event handler to the frontend 296 * process. 297 */ 298 if (iev_frontend) 299 fatalx("%s: received unexpected imsg fd " 300 "to engine", __func__); 301 302 if ((fd = imsg.fd) == -1) 303 fatalx("%s: expected to receive imsg fd to " 304 "engine but didn't receive any", __func__); 305 306 iev_frontend = malloc(sizeof(struct imsgev)); 307 if (iev_frontend == NULL) 308 fatal(NULL); 309 310 imsg_init(&iev_frontend->ibuf, fd); 311 iev_frontend->handler = engine_dispatch_frontend; 312 iev_frontend->events = EV_READ; 313 314 event_set(&iev_frontend->ev, iev_frontend->ibuf.fd, 315 iev_frontend->events, iev_frontend->handler, 316 iev_frontend); 317 event_add(&iev_frontend->ev, NULL); 318 break; 319 case IMSG_RECONF_CONF: 320 if (nconf != NULL) 321 fatalx("%s: IMSG_RECONF_CONF already in " 322 "progress", __func__); 323 if (IMSG_DATA_SIZE(imsg) != sizeof(struct rad_conf)) 324 fatalx("%s: IMSG_RECONF_CONF wrong length: %lu", 325 __func__, IMSG_DATA_SIZE(imsg)); 326 if ((nconf = malloc(sizeof(struct rad_conf))) == NULL) 327 fatal(NULL); 328 memcpy(nconf, imsg.data, sizeof(struct rad_conf)); 329 SIMPLEQ_INIT(&nconf->ra_iface_list); 330 SIMPLEQ_INIT(&nconf->ra_options.ra_rdnss_list); 331 SIMPLEQ_INIT(&nconf->ra_options.ra_dnssl_list); 332 ra_options = &nconf->ra_options; 333 break; 334 case IMSG_RECONF_RA_IFACE: 335 if (IMSG_DATA_SIZE(imsg) != sizeof(struct 336 ra_iface_conf)) 337 fatalx("%s: IMSG_RECONF_RA_IFACE wrong length: " 338 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 339 if ((ra_iface_conf = malloc(sizeof(struct 340 ra_iface_conf))) == NULL) 341 fatal(NULL); 342 memcpy(ra_iface_conf, imsg.data, 343 sizeof(struct ra_iface_conf)); 344 ra_iface_conf->autoprefix = NULL; 345 SIMPLEQ_INIT(&ra_iface_conf->ra_prefix_list); 346 SIMPLEQ_INIT(&ra_iface_conf->ra_options.ra_rdnss_list); 347 SIMPLEQ_INIT(&ra_iface_conf->ra_options.ra_dnssl_list); 348 SIMPLEQ_INSERT_TAIL(&nconf->ra_iface_list, 349 ra_iface_conf, entry); 350 ra_options = &ra_iface_conf->ra_options; 351 break; 352 case IMSG_RECONF_RA_AUTOPREFIX: 353 if (IMSG_DATA_SIZE(imsg) != sizeof(struct 354 ra_prefix_conf)) 355 fatalx("%s: IMSG_RECONF_RA_AUTOPREFIX wrong " 356 "length: %lu", __func__, 357 IMSG_DATA_SIZE(imsg)); 358 if ((ra_iface_conf->autoprefix = malloc(sizeof(struct 359 ra_prefix_conf))) == NULL) 360 fatal(NULL); 361 memcpy(ra_iface_conf->autoprefix, imsg.data, 362 sizeof(struct ra_prefix_conf)); 363 break; 364 case IMSG_RECONF_RA_PREFIX: 365 if (IMSG_DATA_SIZE(imsg) != sizeof(struct 366 ra_prefix_conf)) 367 fatalx("%s: IMSG_RECONF_RA_PREFIX wrong " 368 "length: %lu", __func__, 369 IMSG_DATA_SIZE(imsg)); 370 if ((ra_prefix_conf = malloc(sizeof(struct 371 ra_prefix_conf))) == NULL) 372 fatal(NULL); 373 memcpy(ra_prefix_conf, imsg.data, sizeof(struct 374 ra_prefix_conf)); 375 SIMPLEQ_INSERT_TAIL(&ra_iface_conf->ra_prefix_list, 376 ra_prefix_conf, entry); 377 break; 378 case IMSG_RECONF_RA_RDNSS: 379 if(IMSG_DATA_SIZE(imsg) != sizeof(struct 380 ra_rdnss_conf)) 381 fatalx("%s: IMSG_RECONF_RA_RDNSS wrong length: " 382 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 383 if ((ra_rdnss_conf = malloc(sizeof(struct 384 ra_rdnss_conf))) == NULL) 385 fatal(NULL); 386 memcpy(ra_rdnss_conf, imsg.data, sizeof(struct 387 ra_rdnss_conf)); 388 SIMPLEQ_INSERT_TAIL(&ra_options->ra_rdnss_list, 389 ra_rdnss_conf, entry); 390 break; 391 case IMSG_RECONF_RA_DNSSL: 392 if(IMSG_DATA_SIZE(imsg) != sizeof(struct 393 ra_dnssl_conf)) 394 fatalx("%s: IMSG_RECONF_RA_DNSSL wrong length: " 395 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 396 if ((ra_dnssl_conf = malloc(sizeof(struct 397 ra_dnssl_conf))) == NULL) 398 fatal(NULL); 399 memcpy(ra_dnssl_conf, imsg.data, sizeof(struct 400 ra_dnssl_conf)); 401 SIMPLEQ_INSERT_TAIL(&ra_options->ra_dnssl_list, 402 ra_dnssl_conf, entry); 403 break; 404 case IMSG_RECONF_END: 405 if (nconf == NULL) 406 fatalx("%s: IMSG_RECONF_END without " 407 "IMSG_RECONF_CONF", __func__); 408 merge_config(engine_conf, nconf); 409 nconf = NULL; 410 break; 411 default: 412 log_debug("%s: unexpected imsg %d", __func__, 413 imsg.hdr.type); 414 break; 415 } 416 imsg_free(&imsg); 417 } 418 if (!shut) 419 imsg_event_add(iev); 420 else { 421 /* This pipe is dead. Remove its event handler. */ 422 event_del(&iev->ev); 423 event_loopexit(NULL); 424 } 425 } 426 427 428 void 429 parse_ra_rs(struct imsg_ra_rs *ra_rs) 430 { 431 char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ]; 432 struct icmp6_hdr *hdr; 433 434 hdr = (struct icmp6_hdr *) ra_rs->packet; 435 436 switch (hdr->icmp6_type) { 437 case ND_ROUTER_ADVERT: 438 parse_ra(ra_rs); 439 break; 440 case ND_ROUTER_SOLICIT: 441 parse_rs(ra_rs); 442 break; 443 default: 444 log_warnx("unexpected icmp6_type: %d from %s on %s", 445 hdr->icmp6_type, inet_ntop(AF_INET6, &ra_rs->from.sin6_addr, 446 ntopbuf, INET6_ADDRSTRLEN), if_indextoname(ra_rs->if_index, 447 ifnamebuf)); 448 break; 449 } 450 } 451 452 void 453 parse_ra(struct imsg_ra_rs *ra) 454 { 455 char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ]; 456 log_debug("got RA from %s on %s", 457 inet_ntop(AF_INET6, &ra->from.sin6_addr, ntopbuf, 458 INET6_ADDRSTRLEN), if_indextoname(ra->if_index, 459 ifnamebuf)); 460 /* XXX not yet */ 461 } 462 463 void 464 parse_rs(struct imsg_ra_rs *rs) 465 { 466 struct nd_router_solicit *nd_rs; 467 struct imsg_send_ra send_ra; 468 ssize_t len; 469 const char *hbuf; 470 char ifnamebuf[IFNAMSIZ]; 471 uint8_t *p; 472 473 hbuf = sin6_to_str(&rs->from); 474 475 send_ra.if_index = rs->if_index; 476 memcpy(&send_ra.to, &all_nodes, sizeof(send_ra.to)); 477 478 log_debug("got RS from %s on %s", hbuf, if_indextoname(rs->if_index, 479 ifnamebuf)); 480 481 len = rs->len; 482 483 if (!IN6_IS_ADDR_LINKLOCAL(&rs->from.sin6_addr)) { 484 log_warnx("RA from non link local address %s on %s", hbuf, 485 if_indextoname(rs->if_index, ifnamebuf)); 486 return; 487 } 488 489 if ((size_t)len < sizeof(struct nd_router_solicit)) { 490 log_warnx("received too short message (%ld) from %s", len, 491 hbuf); 492 return; 493 } 494 495 p = rs->packet; 496 nd_rs = (struct nd_router_solicit *)p; 497 len -= sizeof(struct nd_router_solicit); 498 p += sizeof(struct nd_router_solicit); 499 500 if (nd_rs->nd_rs_code != 0) { 501 log_warnx("invalid ICMPv6 code (%d) from %s", nd_rs->nd_rs_code, 502 hbuf); 503 return; 504 } 505 while ((size_t)len >= sizeof(struct nd_opt_hdr)) { 506 struct nd_opt_hdr *nd_opt_hdr = (struct nd_opt_hdr *)p; 507 508 len -= sizeof(struct nd_opt_hdr); 509 p += sizeof(struct nd_opt_hdr); 510 511 if (nd_opt_hdr->nd_opt_len * 8 - 2 > len) { 512 log_warnx("invalid option len: %u > %ld", 513 nd_opt_hdr->nd_opt_len, len); 514 return; 515 } 516 switch (nd_opt_hdr->nd_opt_type) { 517 case ND_OPT_SOURCE_LINKADDR: 518 log_debug("got RS with source linkaddr option"); 519 memcpy(&send_ra.to, &rs->from, sizeof(send_ra.to)); 520 break; 521 default: 522 log_debug("\t\tUNKNOWN: %d", nd_opt_hdr->nd_opt_type); 523 break; 524 } 525 len -= nd_opt_hdr->nd_opt_len * 8 - 2; 526 p += nd_opt_hdr->nd_opt_len * 8 - 2; 527 } 528 engine_imsg_compose_frontend(IMSG_SEND_RA, 0, &send_ra, 529 sizeof(send_ra)); 530 } 531 532 struct engine_iface* 533 find_engine_iface_by_id(uint32_t if_index) 534 { 535 struct engine_iface *engine_iface; 536 537 TAILQ_FOREACH(engine_iface, &engine_interfaces, entry) { 538 if (engine_iface->if_index == if_index) 539 return engine_iface; 540 } 541 return (NULL); 542 } 543 544 void 545 update_iface(uint32_t if_index) 546 { 547 struct engine_iface *engine_iface; 548 struct timeval tv; 549 550 if ((engine_iface = find_engine_iface_by_id(if_index)) == NULL) { 551 engine_iface = calloc(1, sizeof(*engine_iface)); 552 engine_iface->if_index = if_index; 553 evtimer_set(&engine_iface->timer, iface_timeout, engine_iface); 554 TAILQ_INSERT_TAIL(&engine_interfaces, engine_iface, entry); 555 } 556 557 tv.tv_sec = 0; 558 tv.tv_usec = arc4random_uniform(1000000); 559 evtimer_add(&engine_iface->timer, &tv); 560 } 561 562 void 563 remove_iface(uint32_t if_index) 564 { 565 struct engine_iface *engine_iface; 566 struct imsg_send_ra send_ra; 567 char if_name[IF_NAMESIZE]; 568 569 if ((engine_iface = find_engine_iface_by_id(if_index)) == NULL) { 570 /* we don't know this interface, frontend can delete it */ 571 engine_imsg_compose_frontend(IMSG_REMOVE_IF, 0, 572 &if_index, sizeof(if_index)); 573 return; 574 } 575 576 send_ra.if_index = engine_iface->if_index; 577 memcpy(&send_ra.to, &all_nodes, sizeof(send_ra.to)); 578 579 TAILQ_REMOVE(&engine_interfaces, engine_iface, entry); 580 evtimer_del(&engine_iface->timer); 581 582 if (if_indextoname(if_index, if_name) != NULL) 583 engine_imsg_compose_frontend(IMSG_SEND_RA, 0, &send_ra, 584 sizeof(send_ra)); 585 engine_imsg_compose_frontend(IMSG_REMOVE_IF, 0, 586 &engine_iface->if_index, sizeof(engine_iface->if_index)); 587 free(engine_iface); 588 } 589 590 void 591 iface_timeout(int fd, short events, void *arg) 592 { 593 struct engine_iface *engine_iface = (struct engine_iface *)arg; 594 struct imsg_send_ra send_ra; 595 struct timeval tv; 596 597 tv.tv_sec = MIN_RTR_ADV_INTERVAL + 598 arc4random_uniform(MAX_RTR_ADV_INTERVAL - MIN_RTR_ADV_INTERVAL); 599 tv.tv_usec = arc4random_uniform(1000000); 600 601 log_debug("%s new timeout in %lld", __func__, tv.tv_sec); 602 603 evtimer_add(&engine_iface->timer, &tv); 604 605 send_ra.if_index = engine_iface->if_index; 606 memcpy(&send_ra.to, &all_nodes, sizeof(send_ra.to)); 607 engine_imsg_compose_frontend(IMSG_SEND_RA, 0, &send_ra, 608 sizeof(send_ra)); 609 } 610