1 /* $OpenBSD: engine.c,v 1.16 2020/05/20 10:37:02 claudio 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 struct imsgev *iev_frontend; 69 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 rad_process = PROC_ENGINE; 109 setproctitle("%s", log_procnames[rad_process]); 110 log_procinit(log_procnames[rad_process]); 111 112 if (setgroups(1, &pw->pw_gid) || 113 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || 114 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) 115 fatal("can't drop privileges"); 116 117 if (pledge("stdio recvfd", NULL) == -1) 118 fatal("pledge"); 119 120 event_init(); 121 122 /* Setup signal handler(s). */ 123 signal_set(&ev_sigint, SIGINT, engine_sig_handler, NULL); 124 signal_set(&ev_sigterm, SIGTERM, engine_sig_handler, NULL); 125 signal_add(&ev_sigint, NULL); 126 signal_add(&ev_sigterm, NULL); 127 signal(SIGPIPE, SIG_IGN); 128 signal(SIGHUP, SIG_IGN); 129 130 /* Setup pipe and event handler to the main process. */ 131 if ((iev_main = malloc(sizeof(struct imsgev))) == NULL) 132 fatal(NULL); 133 134 imsg_init(&iev_main->ibuf, 3); 135 iev_main->handler = engine_dispatch_main; 136 137 /* Setup event handlers. */ 138 iev_main->events = EV_READ; 139 event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events, 140 iev_main->handler, iev_main); 141 event_add(&iev_main->ev, NULL); 142 143 all_nodes.sin6_len = sizeof(all_nodes); 144 all_nodes.sin6_family = AF_INET6; 145 if (inet_pton(AF_INET6, "ff02::1", &all_nodes.sin6_addr) != 1) 146 fatal("inet_pton"); 147 148 TAILQ_INIT(&engine_interfaces); 149 150 event_dispatch(); 151 152 engine_shutdown(); 153 } 154 155 __dead void 156 engine_shutdown(void) 157 { 158 /* Close pipes. */ 159 msgbuf_clear(&iev_frontend->ibuf.w); 160 close(iev_frontend->ibuf.fd); 161 msgbuf_clear(&iev_main->ibuf.w); 162 close(iev_main->ibuf.fd); 163 164 config_clear(engine_conf); 165 166 free(iev_frontend); 167 free(iev_main); 168 169 log_info("engine exiting"); 170 exit(0); 171 } 172 173 int 174 engine_imsg_compose_frontend(int type, pid_t pid, void *data, uint16_t datalen) 175 { 176 return (imsg_compose_event(iev_frontend, type, 0, pid, -1, 177 data, datalen)); 178 } 179 180 void 181 engine_dispatch_frontend(int fd, short event, void *bula) 182 { 183 struct imsgev *iev = bula; 184 struct imsgbuf *ibuf; 185 struct imsg imsg; 186 struct imsg_ra_rs ra_rs; 187 ssize_t n; 188 uint32_t if_index; 189 int shut = 0, verbose; 190 191 ibuf = &iev->ibuf; 192 193 if (event & EV_READ) { 194 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 195 fatal("imsg_read error"); 196 if (n == 0) /* Connection closed. */ 197 shut = 1; 198 } 199 if (event & EV_WRITE) { 200 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 201 fatal("msgbuf_write"); 202 if (n == 0) /* Connection closed. */ 203 shut = 1; 204 } 205 206 for (;;) { 207 if ((n = imsg_get(ibuf, &imsg)) == -1) 208 fatal("%s: imsg_get error", __func__); 209 if (n == 0) /* No more messages. */ 210 break; 211 212 switch (imsg.hdr.type) { 213 case IMSG_RA_RS: 214 if (IMSG_DATA_SIZE(imsg) != sizeof(ra_rs)) 215 fatalx("%s: IMSG_RA_RS wrong length: %lu", 216 __func__, IMSG_DATA_SIZE(imsg)); 217 memcpy(&ra_rs, imsg.data, sizeof(ra_rs)); 218 parse_ra_rs(&ra_rs); 219 break; 220 case IMSG_UPDATE_IF: 221 if (IMSG_DATA_SIZE(imsg) != sizeof(if_index)) 222 fatalx("%s: IMSG_UPDATE_IF wrong length: %lu", 223 __func__, IMSG_DATA_SIZE(imsg)); 224 memcpy(&if_index, imsg.data, sizeof(if_index)); 225 update_iface(if_index); 226 break; 227 case IMSG_REMOVE_IF: 228 if (IMSG_DATA_SIZE(imsg) != sizeof(if_index)) 229 fatalx("%s: IMSG_REMOVE_IF wrong length: %lu", 230 __func__, IMSG_DATA_SIZE(imsg)); 231 memcpy(&if_index, imsg.data, sizeof(if_index)); 232 remove_iface(if_index); 233 break; 234 case IMSG_CTL_LOG_VERBOSE: 235 if (IMSG_DATA_SIZE(imsg) != sizeof(verbose)) 236 fatalx("%s: IMSG_CTL_LOG_VERBOSE wrong length: " 237 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 238 memcpy(&verbose, imsg.data, sizeof(verbose)); 239 log_setverbose(verbose); 240 break; 241 default: 242 log_debug("%s: unexpected imsg %d", __func__, 243 imsg.hdr.type); 244 break; 245 } 246 imsg_free(&imsg); 247 } 248 if (!shut) 249 imsg_event_add(iev); 250 else { 251 /* This pipe is dead. Remove its event handler. */ 252 event_del(&iev->ev); 253 event_loopexit(NULL); 254 } 255 } 256 257 void 258 engine_dispatch_main(int fd, short event, void *bula) 259 { 260 static struct rad_conf *nconf; 261 static struct ra_iface_conf *ra_iface_conf; 262 static struct ra_options_conf *ra_options; 263 struct imsg imsg; 264 struct imsgev *iev = bula; 265 struct imsgbuf *ibuf; 266 struct ra_prefix_conf *ra_prefix_conf; 267 struct ra_rdnss_conf *ra_rdnss_conf; 268 struct ra_dnssl_conf *ra_dnssl_conf; 269 ssize_t n; 270 int shut = 0; 271 272 ibuf = &iev->ibuf; 273 274 if (event & EV_READ) { 275 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 276 fatal("imsg_read error"); 277 if (n == 0) /* Connection closed. */ 278 shut = 1; 279 } 280 if (event & EV_WRITE) { 281 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 282 fatal("msgbuf_write"); 283 if (n == 0) /* Connection closed. */ 284 shut = 1; 285 } 286 287 for (;;) { 288 if ((n = imsg_get(ibuf, &imsg)) == -1) 289 fatal("%s: imsg_get error", __func__); 290 if (n == 0) /* No more messages. */ 291 break; 292 293 switch (imsg.hdr.type) { 294 case IMSG_SOCKET_IPC: 295 /* 296 * Setup pipe and event handler to the frontend 297 * process. 298 */ 299 if (iev_frontend) 300 fatalx("%s: received unexpected imsg fd " 301 "to engine", __func__); 302 303 if ((fd = imsg.fd) == -1) 304 fatalx("%s: expected to receive imsg fd to " 305 "engine but didn't receive any", __func__); 306 307 iev_frontend = malloc(sizeof(struct imsgev)); 308 if (iev_frontend == NULL) 309 fatal(NULL); 310 311 imsg_init(&iev_frontend->ibuf, fd); 312 iev_frontend->handler = engine_dispatch_frontend; 313 iev_frontend->events = EV_READ; 314 315 event_set(&iev_frontend->ev, iev_frontend->ibuf.fd, 316 iev_frontend->events, iev_frontend->handler, 317 iev_frontend); 318 event_add(&iev_frontend->ev, NULL); 319 break; 320 case IMSG_RECONF_CONF: 321 if (nconf != NULL) 322 fatalx("%s: IMSG_RECONF_CONF already in " 323 "progress", __func__); 324 if (IMSG_DATA_SIZE(imsg) != sizeof(struct rad_conf)) 325 fatalx("%s: IMSG_RECONF_CONF wrong length: %lu", 326 __func__, IMSG_DATA_SIZE(imsg)); 327 if ((nconf = malloc(sizeof(struct rad_conf))) == NULL) 328 fatal(NULL); 329 memcpy(nconf, imsg.data, sizeof(struct rad_conf)); 330 SIMPLEQ_INIT(&nconf->ra_iface_list); 331 SIMPLEQ_INIT(&nconf->ra_options.ra_rdnss_list); 332 SIMPLEQ_INIT(&nconf->ra_options.ra_dnssl_list); 333 ra_options = &nconf->ra_options; 334 break; 335 case IMSG_RECONF_RA_IFACE: 336 if (IMSG_DATA_SIZE(imsg) != sizeof(struct 337 ra_iface_conf)) 338 fatalx("%s: IMSG_RECONF_RA_IFACE wrong length: " 339 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 340 if ((ra_iface_conf = malloc(sizeof(struct 341 ra_iface_conf))) == NULL) 342 fatal(NULL); 343 memcpy(ra_iface_conf, imsg.data, 344 sizeof(struct ra_iface_conf)); 345 ra_iface_conf->autoprefix = NULL; 346 SIMPLEQ_INIT(&ra_iface_conf->ra_prefix_list); 347 SIMPLEQ_INIT(&ra_iface_conf->ra_options.ra_rdnss_list); 348 SIMPLEQ_INIT(&ra_iface_conf->ra_options.ra_dnssl_list); 349 SIMPLEQ_INSERT_TAIL(&nconf->ra_iface_list, 350 ra_iface_conf, entry); 351 ra_options = &ra_iface_conf->ra_options; 352 break; 353 case IMSG_RECONF_RA_AUTOPREFIX: 354 if (IMSG_DATA_SIZE(imsg) != sizeof(struct 355 ra_prefix_conf)) 356 fatalx("%s: IMSG_RECONF_RA_AUTOPREFIX wrong " 357 "length: %lu", __func__, 358 IMSG_DATA_SIZE(imsg)); 359 if ((ra_iface_conf->autoprefix = malloc(sizeof(struct 360 ra_prefix_conf))) == NULL) 361 fatal(NULL); 362 memcpy(ra_iface_conf->autoprefix, imsg.data, 363 sizeof(struct ra_prefix_conf)); 364 break; 365 case IMSG_RECONF_RA_PREFIX: 366 if (IMSG_DATA_SIZE(imsg) != sizeof(struct 367 ra_prefix_conf)) 368 fatalx("%s: IMSG_RECONF_RA_PREFIX wrong " 369 "length: %lu", __func__, 370 IMSG_DATA_SIZE(imsg)); 371 if ((ra_prefix_conf = malloc(sizeof(struct 372 ra_prefix_conf))) == NULL) 373 fatal(NULL); 374 memcpy(ra_prefix_conf, imsg.data, sizeof(struct 375 ra_prefix_conf)); 376 SIMPLEQ_INSERT_TAIL(&ra_iface_conf->ra_prefix_list, 377 ra_prefix_conf, entry); 378 break; 379 case IMSG_RECONF_RA_RDNSS: 380 if(IMSG_DATA_SIZE(imsg) != sizeof(struct 381 ra_rdnss_conf)) 382 fatalx("%s: IMSG_RECONF_RA_RDNSS wrong length: " 383 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 384 if ((ra_rdnss_conf = malloc(sizeof(struct 385 ra_rdnss_conf))) == NULL) 386 fatal(NULL); 387 memcpy(ra_rdnss_conf, imsg.data, sizeof(struct 388 ra_rdnss_conf)); 389 SIMPLEQ_INSERT_TAIL(&ra_options->ra_rdnss_list, 390 ra_rdnss_conf, entry); 391 break; 392 case IMSG_RECONF_RA_DNSSL: 393 if(IMSG_DATA_SIZE(imsg) != sizeof(struct 394 ra_dnssl_conf)) 395 fatalx("%s: IMSG_RECONF_RA_DNSSL wrong length: " 396 "%lu", __func__, IMSG_DATA_SIZE(imsg)); 397 if ((ra_dnssl_conf = malloc(sizeof(struct 398 ra_dnssl_conf))) == NULL) 399 fatal(NULL); 400 memcpy(ra_dnssl_conf, imsg.data, sizeof(struct 401 ra_dnssl_conf)); 402 SIMPLEQ_INSERT_TAIL(&ra_options->ra_dnssl_list, 403 ra_dnssl_conf, entry); 404 break; 405 case IMSG_RECONF_END: 406 if (nconf == NULL) 407 fatalx("%s: IMSG_RECONF_END without " 408 "IMSG_RECONF_CONF", __func__); 409 merge_config(engine_conf, nconf); 410 nconf = NULL; 411 break; 412 default: 413 log_debug("%s: unexpected imsg %d", __func__, 414 imsg.hdr.type); 415 break; 416 } 417 imsg_free(&imsg); 418 } 419 if (!shut) 420 imsg_event_add(iev); 421 else { 422 /* This pipe is dead. Remove its event handler. */ 423 event_del(&iev->ev); 424 event_loopexit(NULL); 425 } 426 } 427 428 429 void 430 parse_ra_rs(struct imsg_ra_rs *ra_rs) 431 { 432 char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ]; 433 struct icmp6_hdr *hdr; 434 435 hdr = (struct icmp6_hdr *) ra_rs->packet; 436 437 switch (hdr->icmp6_type) { 438 case ND_ROUTER_ADVERT: 439 parse_ra(ra_rs); 440 break; 441 case ND_ROUTER_SOLICIT: 442 parse_rs(ra_rs); 443 break; 444 default: 445 log_warnx("unexpected icmp6_type: %d from %s on %s", 446 hdr->icmp6_type, inet_ntop(AF_INET6, &ra_rs->from.sin6_addr, 447 ntopbuf, INET6_ADDRSTRLEN), if_indextoname(ra_rs->if_index, 448 ifnamebuf)); 449 break; 450 } 451 } 452 453 void 454 parse_ra(struct imsg_ra_rs *ra) 455 { 456 char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ]; 457 log_debug("got RA from %s on %s", 458 inet_ntop(AF_INET6, &ra->from.sin6_addr, ntopbuf, 459 INET6_ADDRSTRLEN), if_indextoname(ra->if_index, 460 ifnamebuf)); 461 /* XXX not yet */ 462 } 463 464 void 465 parse_rs(struct imsg_ra_rs *rs) 466 { 467 struct nd_router_solicit *nd_rs; 468 struct imsg_send_ra send_ra; 469 ssize_t len; 470 const char *hbuf; 471 char ifnamebuf[IFNAMSIZ]; 472 uint8_t *p; 473 474 hbuf = sin6_to_str(&rs->from); 475 476 send_ra.if_index = rs->if_index; 477 memcpy(&send_ra.to, &all_nodes, sizeof(send_ra.to)); 478 479 log_debug("got RS from %s on %s", hbuf, if_indextoname(rs->if_index, 480 ifnamebuf)); 481 482 len = rs->len; 483 484 if (!IN6_IS_ADDR_LINKLOCAL(&rs->from.sin6_addr)) { 485 log_warnx("RA from non link local 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