1 /* $OpenBSD: engine.c,v 1.19 2021/05/13 11:22:15 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 IN6_IS_ADDR_UNSPECIFIED(&rs->from.sin6_addr))) { 485 log_warnx("RA from invalid address %s on %s", hbuf, 486 if_indextoname(rs->if_index, ifnamebuf)); 487 return; 488 } 489 490 if ((size_t)len < sizeof(struct nd_router_solicit)) { 491 log_warnx("received too short message (%ld) from %s", len, 492 hbuf); 493 return; 494 } 495 496 p = rs->packet; 497 nd_rs = (struct nd_router_solicit *)p; 498 len -= sizeof(struct nd_router_solicit); 499 p += sizeof(struct nd_router_solicit); 500 501 if (nd_rs->nd_rs_code != 0) { 502 log_warnx("invalid ICMPv6 code (%d) from %s", nd_rs->nd_rs_code, 503 hbuf); 504 return; 505 } 506 while ((size_t)len >= sizeof(struct nd_opt_hdr)) { 507 struct nd_opt_hdr *nd_opt_hdr = (struct nd_opt_hdr *)p; 508 509 len -= sizeof(struct nd_opt_hdr); 510 p += sizeof(struct nd_opt_hdr); 511 512 if (nd_opt_hdr->nd_opt_len * 8 - 2 > len) { 513 log_warnx("invalid option len: %u > %ld", 514 nd_opt_hdr->nd_opt_len, len); 515 return; 516 } 517 switch (nd_opt_hdr->nd_opt_type) { 518 case ND_OPT_SOURCE_LINKADDR: 519 log_debug("got RS with source linkaddr option"); 520 memcpy(&send_ra.to, &rs->from, sizeof(send_ra.to)); 521 break; 522 default: 523 log_debug("\t\tUNKNOWN: %d", nd_opt_hdr->nd_opt_type); 524 break; 525 } 526 len -= nd_opt_hdr->nd_opt_len * 8 - 2; 527 p += nd_opt_hdr->nd_opt_len * 8 - 2; 528 } 529 engine_imsg_compose_frontend(IMSG_SEND_RA, 0, &send_ra, 530 sizeof(send_ra)); 531 } 532 533 struct engine_iface* 534 find_engine_iface_by_id(uint32_t if_index) 535 { 536 struct engine_iface *engine_iface; 537 538 TAILQ_FOREACH(engine_iface, &engine_interfaces, entry) { 539 if (engine_iface->if_index == if_index) 540 return engine_iface; 541 } 542 return (NULL); 543 } 544 545 void 546 update_iface(uint32_t if_index) 547 { 548 struct engine_iface *engine_iface; 549 struct timeval tv; 550 551 if ((engine_iface = find_engine_iface_by_id(if_index)) == NULL) { 552 engine_iface = calloc(1, sizeof(*engine_iface)); 553 engine_iface->if_index = if_index; 554 evtimer_set(&engine_iface->timer, iface_timeout, engine_iface); 555 TAILQ_INSERT_TAIL(&engine_interfaces, engine_iface, entry); 556 } 557 558 tv.tv_sec = 0; 559 tv.tv_usec = arc4random_uniform(1000000); 560 evtimer_add(&engine_iface->timer, &tv); 561 } 562 563 void 564 remove_iface(uint32_t if_index) 565 { 566 struct engine_iface *engine_iface; 567 struct imsg_send_ra send_ra; 568 char if_name[IF_NAMESIZE]; 569 570 if ((engine_iface = find_engine_iface_by_id(if_index)) == NULL) { 571 /* we don't know this interface, frontend can delete it */ 572 engine_imsg_compose_frontend(IMSG_REMOVE_IF, 0, 573 &if_index, sizeof(if_index)); 574 return; 575 } 576 577 send_ra.if_index = engine_iface->if_index; 578 memcpy(&send_ra.to, &all_nodes, sizeof(send_ra.to)); 579 580 TAILQ_REMOVE(&engine_interfaces, engine_iface, entry); 581 evtimer_del(&engine_iface->timer); 582 583 if (if_indextoname(if_index, if_name) != NULL) 584 engine_imsg_compose_frontend(IMSG_SEND_RA, 0, &send_ra, 585 sizeof(send_ra)); 586 engine_imsg_compose_frontend(IMSG_REMOVE_IF, 0, 587 &engine_iface->if_index, sizeof(engine_iface->if_index)); 588 free(engine_iface); 589 } 590 591 void 592 iface_timeout(int fd, short events, void *arg) 593 { 594 struct engine_iface *engine_iface = (struct engine_iface *)arg; 595 struct imsg_send_ra send_ra; 596 struct timeval tv; 597 598 tv.tv_sec = MIN_RTR_ADV_INTERVAL + 599 arc4random_uniform(MAX_RTR_ADV_INTERVAL - MIN_RTR_ADV_INTERVAL); 600 tv.tv_usec = arc4random_uniform(1000000); 601 602 log_debug("%s new timeout in %lld", __func__, tv.tv_sec); 603 604 evtimer_add(&engine_iface->timer, &tv); 605 606 send_ra.if_index = engine_iface->if_index; 607 memcpy(&send_ra.to, &all_nodes, sizeof(send_ra.to)); 608 engine_imsg_compose_frontend(IMSG_SEND_RA, 0, &send_ra, 609 sizeof(send_ra)); 610 } 611