1 /* $OpenBSD: engine.c,v 1.10 2019/01/29 15:43:33 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 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.hdr.len != IMSG_HEADER_SIZE + sizeof(ra_rs)) 215 fatal("%s: IMSG_RA_RS wrong length: %d", 216 __func__, imsg.hdr.len); 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.hdr.len != IMSG_HEADER_SIZE + sizeof(if_index)) 222 fatal("%s: IMSG_UPDATE_IF wrong length: %d", 223 __func__, imsg.hdr.len); 224 memcpy(&if_index, imsg.data, sizeof(if_index)); 225 update_iface(if_index); 226 break; 227 case IMSG_REMOVE_IF: 228 if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(if_index)) 229 fatal("%s: IMSG_REMOVE_IF wrong length: %d", 230 __func__, imsg.hdr.len); 231 memcpy(&if_index, imsg.data, sizeof(if_index)); 232 remove_iface(if_index); 233 break; 234 case IMSG_CTL_LOG_VERBOSE: 235 /* Already checked by frontend. */ 236 memcpy(&verbose, imsg.data, sizeof(verbose)); 237 log_setverbose(verbose); 238 break; 239 default: 240 log_debug("%s: unexpected imsg %d", __func__, 241 imsg.hdr.type); 242 break; 243 } 244 imsg_free(&imsg); 245 } 246 if (!shut) 247 imsg_event_add(iev); 248 else { 249 /* This pipe is dead. Remove its event handler. */ 250 event_del(&iev->ev); 251 event_loopexit(NULL); 252 } 253 } 254 255 void 256 engine_dispatch_main(int fd, short event, void *bula) 257 { 258 static struct rad_conf *nconf; 259 static struct ra_iface_conf *ra_iface_conf; 260 static struct ra_options_conf *ra_options; 261 struct imsg imsg; 262 struct imsgev *iev = bula; 263 struct imsgbuf *ibuf; 264 struct ra_prefix_conf *ra_prefix_conf; 265 struct ra_rdnss_conf *ra_rdnss_conf; 266 struct ra_dnssl_conf *ra_dnssl_conf; 267 ssize_t n; 268 int shut = 0; 269 270 ibuf = &iev->ibuf; 271 272 if (event & EV_READ) { 273 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 274 fatal("imsg_read error"); 275 if (n == 0) /* Connection closed. */ 276 shut = 1; 277 } 278 if (event & EV_WRITE) { 279 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 280 fatal("msgbuf_write"); 281 if (n == 0) /* Connection closed. */ 282 shut = 1; 283 } 284 285 for (;;) { 286 if ((n = imsg_get(ibuf, &imsg)) == -1) 287 fatal("%s: imsg_get error", __func__); 288 if (n == 0) /* No more messages. */ 289 break; 290 291 switch (imsg.hdr.type) { 292 case IMSG_SOCKET_IPC: 293 /* 294 * Setup pipe and event handler to the frontend 295 * process. 296 */ 297 if (iev_frontend) { 298 log_warnx("%s: received unexpected imsg fd " 299 "to engine", __func__); 300 break; 301 } 302 if ((fd = imsg.fd) == -1) { 303 log_warnx("%s: expected to receive imsg fd to " 304 "engine but didn't receive any", __func__); 305 break; 306 } 307 308 iev_frontend = malloc(sizeof(struct imsgev)); 309 if (iev_frontend == NULL) 310 fatal(NULL); 311 312 imsg_init(&iev_frontend->ibuf, fd); 313 iev_frontend->handler = engine_dispatch_frontend; 314 iev_frontend->events = EV_READ; 315 316 event_set(&iev_frontend->ev, iev_frontend->ibuf.fd, 317 iev_frontend->events, iev_frontend->handler, 318 iev_frontend); 319 event_add(&iev_frontend->ev, NULL); 320 break; 321 case IMSG_RECONF_CONF: 322 if ((nconf = malloc(sizeof(struct rad_conf))) == NULL) 323 fatal(NULL); 324 memcpy(nconf, imsg.data, sizeof(struct rad_conf)); 325 SIMPLEQ_INIT(&nconf->ra_iface_list); 326 SIMPLEQ_INIT(&nconf->ra_options.ra_rdnss_list); 327 SIMPLEQ_INIT(&nconf->ra_options.ra_dnssl_list); 328 ra_options = &nconf->ra_options; 329 break; 330 case IMSG_RECONF_RA_IFACE: 331 if ((ra_iface_conf = malloc(sizeof(struct 332 ra_iface_conf))) == NULL) 333 fatal(NULL); 334 memcpy(ra_iface_conf, imsg.data, 335 sizeof(struct ra_iface_conf)); 336 ra_iface_conf->autoprefix = NULL; 337 SIMPLEQ_INIT(&ra_iface_conf->ra_prefix_list); 338 SIMPLEQ_INIT(&ra_iface_conf->ra_options.ra_rdnss_list); 339 SIMPLEQ_INIT(&ra_iface_conf->ra_options.ra_dnssl_list); 340 SIMPLEQ_INSERT_TAIL(&nconf->ra_iface_list, 341 ra_iface_conf, entry); 342 ra_options = &ra_iface_conf->ra_options; 343 break; 344 case IMSG_RECONF_RA_AUTOPREFIX: 345 if ((ra_iface_conf->autoprefix = malloc(sizeof(struct 346 ra_prefix_conf))) == NULL) 347 fatal(NULL); 348 memcpy(ra_iface_conf->autoprefix, imsg.data, 349 sizeof(struct ra_prefix_conf)); 350 break; 351 case IMSG_RECONF_RA_PREFIX: 352 if ((ra_prefix_conf = malloc(sizeof(struct 353 ra_prefix_conf))) == NULL) 354 fatal(NULL); 355 memcpy(ra_prefix_conf, imsg.data, sizeof(struct 356 ra_prefix_conf)); 357 SIMPLEQ_INSERT_TAIL(&ra_iface_conf->ra_prefix_list, 358 ra_prefix_conf, entry); 359 break; 360 case IMSG_RECONF_RA_RDNSS: 361 if ((ra_rdnss_conf = malloc(sizeof(struct 362 ra_rdnss_conf))) == NULL) 363 fatal(NULL); 364 memcpy(ra_rdnss_conf, imsg.data, sizeof(struct 365 ra_rdnss_conf)); 366 SIMPLEQ_INSERT_TAIL(&ra_options->ra_rdnss_list, 367 ra_rdnss_conf, entry); 368 break; 369 case IMSG_RECONF_RA_DNSSL: 370 if ((ra_dnssl_conf = malloc(sizeof(struct 371 ra_dnssl_conf))) == NULL) 372 fatal(NULL); 373 memcpy(ra_dnssl_conf, imsg.data, sizeof(struct 374 ra_dnssl_conf)); 375 SIMPLEQ_INSERT_TAIL(&ra_options->ra_dnssl_list, 376 ra_dnssl_conf, entry); 377 break; 378 case IMSG_RECONF_END: 379 merge_config(engine_conf, nconf); 380 nconf = NULL; 381 break; 382 default: 383 log_debug("%s: unexpected imsg %d", __func__, 384 imsg.hdr.type); 385 break; 386 } 387 imsg_free(&imsg); 388 } 389 if (!shut) 390 imsg_event_add(iev); 391 else { 392 /* This pipe is dead. Remove its event handler. */ 393 event_del(&iev->ev); 394 event_loopexit(NULL); 395 } 396 } 397 398 399 void 400 parse_ra_rs(struct imsg_ra_rs *ra_rs) 401 { 402 char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ]; 403 struct icmp6_hdr *hdr; 404 405 hdr = (struct icmp6_hdr *) ra_rs->packet; 406 407 switch (hdr->icmp6_type) { 408 case ND_ROUTER_ADVERT: 409 parse_ra(ra_rs); 410 break; 411 case ND_ROUTER_SOLICIT: 412 parse_rs(ra_rs); 413 break; 414 default: 415 log_warnx("unexpected icmp6_type: %d from %s on %s", 416 hdr->icmp6_type, inet_ntop(AF_INET6, &ra_rs->from.sin6_addr, 417 ntopbuf, INET6_ADDRSTRLEN), if_indextoname(ra_rs->if_index, 418 ifnamebuf)); 419 break; 420 } 421 } 422 423 void 424 parse_ra(struct imsg_ra_rs *ra) 425 { 426 char ntopbuf[INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ]; 427 log_debug("got RA from %s on %s", 428 inet_ntop(AF_INET6, &ra->from.sin6_addr, ntopbuf, 429 INET6_ADDRSTRLEN), if_indextoname(ra->if_index, 430 ifnamebuf)); 431 /* XXX not yet */ 432 } 433 434 void 435 parse_rs(struct imsg_ra_rs *rs) 436 { 437 struct nd_router_solicit *nd_rs; 438 struct imsg_send_ra send_ra; 439 ssize_t len; 440 const char *hbuf; 441 char ifnamebuf[IFNAMSIZ]; 442 uint8_t *p; 443 444 hbuf = sin6_to_str(&rs->from); 445 446 send_ra.if_index = rs->if_index; 447 memcpy(&send_ra.to, &all_nodes, sizeof(send_ra.to)); 448 449 log_debug("got RS from %s on %s", hbuf, if_indextoname(rs->if_index, 450 ifnamebuf)); 451 452 len = rs->len; 453 454 if (!IN6_IS_ADDR_LINKLOCAL(&rs->from.sin6_addr)) { 455 log_warnx("RA from non link local address %s", hbuf); 456 return; 457 } 458 459 if ((size_t)len < sizeof(struct nd_router_solicit)) { 460 log_warnx("received too short message (%ld) from %s", len, 461 hbuf); 462 return; 463 } 464 465 p = rs->packet; 466 nd_rs = (struct nd_router_solicit *)p; 467 len -= sizeof(struct nd_router_solicit); 468 p += sizeof(struct nd_router_solicit); 469 470 if (nd_rs->nd_rs_code != 0) { 471 log_warnx("invalid ICMPv6 code (%d) from %s", nd_rs->nd_rs_code, 472 hbuf); 473 return; 474 } 475 while ((size_t)len >= sizeof(struct nd_opt_hdr)) { 476 struct nd_opt_hdr *nd_opt_hdr = (struct nd_opt_hdr *)p; 477 478 len -= sizeof(struct nd_opt_hdr); 479 p += sizeof(struct nd_opt_hdr); 480 481 if (nd_opt_hdr->nd_opt_len * 8 - 2 > len) { 482 log_warnx("invalid option len: %u > %ld", 483 nd_opt_hdr->nd_opt_len, len); 484 return; 485 } 486 switch (nd_opt_hdr->nd_opt_type) { 487 case ND_OPT_SOURCE_LINKADDR: 488 log_debug("got RS with source linkaddr option"); 489 memcpy(&send_ra.to, &rs->from, sizeof(send_ra.to)); 490 break; 491 default: 492 log_debug("\t\tUNKNOWN: %d", nd_opt_hdr->nd_opt_type); 493 break; 494 } 495 len -= nd_opt_hdr->nd_opt_len * 8 - 2; 496 p += nd_opt_hdr->nd_opt_len * 8 - 2; 497 } 498 engine_imsg_compose_frontend(IMSG_SEND_RA, 0, &send_ra, 499 sizeof(send_ra)); 500 } 501 502 struct engine_iface* 503 find_engine_iface_by_id(uint32_t if_index) 504 { 505 struct engine_iface *engine_iface; 506 507 TAILQ_FOREACH(engine_iface, &engine_interfaces, entry) { 508 if (engine_iface->if_index == if_index) 509 return engine_iface; 510 } 511 return (NULL); 512 } 513 514 void 515 update_iface(uint32_t if_index) 516 { 517 struct engine_iface *engine_iface; 518 struct timeval tv; 519 520 if ((engine_iface = find_engine_iface_by_id(if_index)) == NULL) { 521 engine_iface = calloc(1, sizeof(*engine_iface)); 522 engine_iface->if_index = if_index; 523 evtimer_set(&engine_iface->timer, iface_timeout, engine_iface); 524 TAILQ_INSERT_TAIL(&engine_interfaces, engine_iface, entry); 525 } 526 527 tv.tv_sec = 0; 528 tv.tv_usec = arc4random_uniform(1000000); 529 evtimer_add(&engine_iface->timer, &tv); 530 } 531 532 void 533 remove_iface(uint32_t if_index) 534 { 535 struct engine_iface *engine_iface; 536 struct imsg_send_ra send_ra; 537 char if_name[IF_NAMESIZE]; 538 539 if ((engine_iface = find_engine_iface_by_id(if_index)) == NULL) { 540 /* we don't know this interface, frontend can delete it */ 541 engine_imsg_compose_frontend(IMSG_REMOVE_IF, 0, 542 &if_index, sizeof(if_index)); 543 return; 544 } 545 546 send_ra.if_index = engine_iface->if_index; 547 memcpy(&send_ra.to, &all_nodes, sizeof(send_ra.to)); 548 549 TAILQ_REMOVE(&engine_interfaces, engine_iface, entry); 550 evtimer_del(&engine_iface->timer); 551 552 if (if_indextoname(if_index, if_name) != NULL) 553 engine_imsg_compose_frontend(IMSG_SEND_RA, 0, &send_ra, 554 sizeof(send_ra)); 555 engine_imsg_compose_frontend(IMSG_REMOVE_IF, 0, 556 &engine_iface->if_index, sizeof(engine_iface->if_index)); 557 free(engine_iface); 558 } 559 560 void 561 iface_timeout(int fd, short events, void *arg) 562 { 563 struct engine_iface *engine_iface = (struct engine_iface *)arg; 564 struct imsg_send_ra send_ra; 565 struct timeval tv; 566 567 tv.tv_sec = MIN_RTR_ADV_INTERVAL + 568 arc4random_uniform(MAX_RTR_ADV_INTERVAL - MIN_RTR_ADV_INTERVAL); 569 tv.tv_usec = arc4random_uniform(1000000); 570 571 log_debug("%s new timeout in %lld", __func__, tv.tv_sec); 572 573 evtimer_add(&engine_iface->timer, &tv); 574 575 send_ra.if_index = engine_iface->if_index; 576 memcpy(&send_ra.to, &all_nodes, sizeof(send_ra.to)); 577 engine_imsg_compose_frontend(IMSG_SEND_RA, 0, &send_ra, 578 sizeof(send_ra)); 579 } 580