1 /* $OpenBSD: dvmrpd.c,v 1.27 2021/01/19 12:29:46 claudio Exp $ */ 2 3 /* 4 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> 5 * Copyright (c) 2005, 2006 Esben Norby <norby@openbsd.org> 6 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> 7 * 8 * Permission to use, copy, modify, and distribute this software for any 9 * purpose with or without fee is hereby granted, provided that the above 10 * copyright notice and this permission notice appear in all copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 */ 20 21 #include <sys/types.h> 22 #include <sys/socket.h> 23 #include <sys/queue.h> 24 #include <sys/time.h> 25 #include <sys/stat.h> 26 #include <sys/sysctl.h> 27 #include <sys/wait.h> 28 29 #include <netinet/in.h> 30 #include <arpa/inet.h> 31 32 #include <event.h> 33 #include <err.h> 34 #include <errno.h> 35 #include <pwd.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <signal.h> 40 #include <unistd.h> 41 #include <util.h> 42 43 #include "igmp.h" 44 #include "dvmrpd.h" 45 #include "dvmrp.h" 46 #include "dvmrpe.h" 47 #include "control.h" 48 #include "log.h" 49 #include "rde.h" 50 51 void main_sig_handler(int, short, void *); 52 __dead void usage(void); 53 __dead void dvmrpd_shutdown(void); 54 55 void main_dispatch_dvmrpe(int, short, void *); 56 void main_dispatch_rde(int, short, void *); 57 void main_imsg_compose_dvmrpe(int, pid_t, void *, u_int16_t); 58 void main_imsg_compose_rde(int, pid_t, void *, u_int16_t); 59 60 int pipe_parent2dvmrpe[2]; 61 int pipe_parent2rde[2]; 62 int pipe_dvmrpe2rde[2]; 63 64 struct dvmrpd_conf *conf = NULL; 65 static struct imsgev *iev_dvmrpe; 66 static struct imsgev *iev_rde; 67 68 pid_t dvmrpe_pid; 69 pid_t rde_pid; 70 71 void 72 main_sig_handler(int sig, short event, void *arg) 73 { 74 /* signal handler rules don't apply, libevent decouples for us */ 75 switch (sig) { 76 case SIGTERM: 77 case SIGINT: 78 dvmrpd_shutdown(); 79 /* NOTREACHED */ 80 case SIGHUP: 81 /* reconfigure */ 82 /* ... */ 83 break; 84 default: 85 fatalx("unexpected signal"); 86 /* NOTREACHED */ 87 } 88 } 89 90 __dead void 91 usage(void) 92 { 93 extern char *__progname; 94 95 fprintf(stderr, "usage: %s [-dnv] [-f file]\n", __progname); 96 exit(1); 97 } 98 99 int 100 main(int argc, char *argv[]) 101 { 102 struct event ev_sigint, ev_sigterm, ev_sighup; 103 char *conffile; 104 int ch, opts = 0; 105 int debug = 0; 106 int ipmforwarding; 107 int mib[4]; 108 size_t len; 109 110 conffile = CONF_FILE; 111 log_procname = "parent"; 112 113 log_init(1); /* log to stderr until daemonized */ 114 log_verbose(1); 115 116 while ((ch = getopt(argc, argv, "df:nv")) != -1) { 117 switch (ch) { 118 case 'd': 119 debug = 1; 120 break; 121 case 'f': 122 conffile = optarg; 123 break; 124 case 'n': 125 opts |= DVMRPD_OPT_NOACTION; 126 break; 127 case 'v': 128 if (opts & DVMRPD_OPT_VERBOSE) 129 opts |= DVMRPD_OPT_VERBOSE2; 130 opts |= DVMRPD_OPT_VERBOSE; 131 log_verbose(1); 132 break; 133 default: 134 usage(); 135 /* NOTREACHED */ 136 } 137 } 138 139 argc -= optind; 140 argv += optind; 141 if (argc > 0) 142 usage(); 143 144 log_init(debug); 145 log_verbose(opts & DVMRPD_OPT_VERBOSE); 146 147 /* multicast IP forwarding must be enabled */ 148 mib[0] = CTL_NET; 149 mib[1] = PF_INET; 150 mib[2] = IPPROTO_IP; 151 mib[3] = IPCTL_MFORWARDING; 152 len = sizeof(ipmforwarding); 153 if (sysctl(mib, 4, &ipmforwarding, &len, NULL, 0) == -1) 154 err(1, "sysctl"); 155 156 if (!ipmforwarding) 157 errx(1, "multicast IP forwarding not enabled"); 158 159 /* fetch interfaces early */ 160 kif_init(); 161 162 /* parse config file */ 163 if ((conf = parse_config(conffile, opts)) == NULL ) 164 exit(1); 165 166 if (conf->opts & DVMRPD_OPT_NOACTION) { 167 if (conf->opts & DVMRPD_OPT_VERBOSE) 168 print_config(conf); 169 else 170 fprintf(stderr, "configuration OK\n"); 171 exit(0); 172 } 173 174 /* check for root privileges */ 175 if (geteuid()) 176 errx(1, "need root privileges"); 177 178 /* check for dvmrpd user */ 179 if (getpwnam(DVMRPD_USER) == NULL) 180 errx(1, "unknown user %s", DVMRPD_USER); 181 182 /* start logging */ 183 log_init(1); 184 185 if (!debug) 186 daemon(1, 0); 187 188 log_info("startup"); 189 190 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 191 PF_UNSPEC, pipe_parent2dvmrpe) == -1) 192 fatal("socketpair"); 193 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 194 PF_UNSPEC, pipe_parent2rde) == -1) 195 fatal("socketpair"); 196 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 197 PF_UNSPEC, pipe_dvmrpe2rde) == -1) 198 fatal("socketpair"); 199 200 /* start children */ 201 rde_pid = rde(conf, pipe_parent2rde, pipe_dvmrpe2rde, 202 pipe_parent2dvmrpe); 203 dvmrpe_pid = dvmrpe(conf, pipe_parent2dvmrpe, pipe_dvmrpe2rde, 204 pipe_parent2rde); 205 206 /* create the raw ip socket */ 207 if ((conf->mroute_socket = socket(AF_INET, 208 SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, 209 IPPROTO_IGMP)) == -1) 210 fatal("error creating raw socket"); 211 212 if_set_recvbuf(conf->mroute_socket); 213 214 if (mrt_init(conf->mroute_socket)) 215 fatal("multicast routing not enabled in kernel"); 216 217 event_init(); 218 219 /* setup signal handler */ 220 signal_set(&ev_sigint, SIGINT, main_sig_handler, NULL); 221 signal_set(&ev_sigterm, SIGTERM, main_sig_handler, NULL); 222 signal_set(&ev_sighup, SIGHUP, main_sig_handler, NULL); 223 signal_add(&ev_sigint, NULL); 224 signal_add(&ev_sigterm, NULL); 225 signal_add(&ev_sighup, NULL); 226 signal(SIGPIPE, SIG_IGN); 227 228 /* setup pipes to children */ 229 close(pipe_parent2dvmrpe[1]); 230 close(pipe_parent2rde[1]); 231 close(pipe_dvmrpe2rde[0]); 232 close(pipe_dvmrpe2rde[1]); 233 234 if ((iev_dvmrpe = malloc(sizeof(struct imsgev))) == NULL || 235 (iev_rde = malloc(sizeof(struct imsgev))) == NULL) 236 fatal(NULL); 237 imsg_init(&iev_dvmrpe->ibuf, pipe_parent2dvmrpe[0]); 238 imsg_init(&iev_rde->ibuf, pipe_parent2rde[0]); 239 iev_dvmrpe->handler = main_dispatch_dvmrpe; 240 iev_rde->handler = main_dispatch_rde; 241 242 /* setup event handler */ 243 iev_dvmrpe->events = EV_READ; 244 event_set(&iev_dvmrpe->ev, iev_dvmrpe->ibuf.fd, iev_dvmrpe->events, 245 iev_dvmrpe->handler, iev_dvmrpe); 246 event_add(&iev_dvmrpe->ev, NULL); 247 248 iev_rde->events = EV_READ; 249 event_set(&iev_rde->ev, iev_rde->ibuf.fd, iev_rde->events, 250 iev_rde->handler, iev_rde); 251 event_add(&iev_rde->ev, NULL); 252 253 if (kmr_init(!(conf->flags & DVMRPD_FLAG_NO_FIB_UPDATE)) == -1) 254 dvmrpd_shutdown(); 255 if (kr_init() == -1) 256 dvmrpd_shutdown(); 257 258 event_set(&conf->ev, conf->mroute_socket, EV_READ|EV_PERSIST, 259 kmr_recv_msg, conf); 260 event_add(&conf->ev, NULL); 261 262 event_dispatch(); 263 264 dvmrpd_shutdown(); 265 /* NOTREACHED */ 266 return (0); 267 } 268 269 __dead void 270 dvmrpd_shutdown(void) 271 { 272 struct iface *iface; 273 pid_t pid; 274 int status; 275 276 /* close pipes */ 277 msgbuf_clear(&iev_dvmrpe->ibuf.w); 278 close(iev_dvmrpe->ibuf.fd); 279 msgbuf_clear(&iev_rde->ibuf.w); 280 close(iev_rde->ibuf.fd); 281 282 control_cleanup(); 283 kmr_shutdown(); 284 kr_shutdown(); 285 LIST_FOREACH(iface, &conf->iface_list, entry) { 286 if_del(iface); 287 } 288 mrt_done(conf->mroute_socket); 289 290 log_debug("waiting for children to terminate"); 291 do { 292 pid = wait(&status); 293 if (pid == -1) { 294 if (errno != EINTR && errno != ECHILD) 295 fatal("wait"); 296 } else if (WIFSIGNALED(status)) 297 log_warnx("%s terminated; signal %d", 298 (pid == rde_pid) ? "route decision engine" : 299 "dvmrp engine", WTERMSIG(status)); 300 } while (pid != -1 || (pid == -1 && errno == EINTR)); 301 302 free(iev_dvmrpe); 303 free(iev_rde); 304 305 log_info("terminating"); 306 exit(0); 307 } 308 309 /* imsg handling */ 310 void 311 main_dispatch_dvmrpe(int fd, short event, void *bula) 312 { 313 struct imsgev *iev = bula; 314 struct imsgbuf *ibuf = &iev->ibuf; 315 struct imsg imsg; 316 ssize_t n; 317 int shut = 0, verbose; 318 319 if (event & EV_READ) { 320 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 321 fatal("imsg_read error"); 322 if (n == 0) /* connection closed */ 323 shut = 1; 324 } 325 if (event & EV_WRITE) { 326 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 327 fatal("msgbuf_write"); 328 if (n == 0) /* connection closed */ 329 shut = 1; 330 } 331 332 for (;;) { 333 if ((n = imsg_get(ibuf, &imsg)) == -1) 334 fatal("imsg_get"); 335 336 if (n == 0) 337 break; 338 339 switch (imsg.hdr.type) { 340 case IMSG_CTL_RELOAD: 341 log_debug("main_dispatch_dvmrpe: IMSG_CTL_RELOAD"); 342 /* reconfig */ 343 break; 344 case IMSG_CTL_MFC_COUPLE: 345 kmr_mfc_couple(); 346 break; 347 case IMSG_CTL_MFC_DECOUPLE: 348 kmr_mfc_decouple(); 349 break; 350 case IMSG_CTL_LOG_VERBOSE: 351 /* already checked by dvmrpe */ 352 memcpy(&verbose, imsg.data, sizeof(verbose)); 353 log_verbose(verbose); 354 break; 355 default: 356 log_debug("main_dispatch_dvmrpe: error handling " 357 "imsg %d", imsg.hdr.type); 358 break; 359 } 360 imsg_free(&imsg); 361 } 362 if (!shut) 363 imsg_event_add(iev); 364 else { 365 /* this pipe is dead, so remove the event handler */ 366 event_del(&iev->ev); 367 event_loopexit(NULL); 368 } 369 } 370 371 void 372 main_dispatch_rde(int fd, short event, void *bula) 373 { 374 struct mfc mfc; 375 struct imsgev *iev = bula; 376 struct imsgbuf *ibuf = &iev->ibuf; 377 struct imsg imsg; 378 ssize_t n; 379 int shut = 0; 380 381 if (event & EV_READ) { 382 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 383 fatal("imsg_read error"); 384 if (n == 0) /* connection closed */ 385 shut = 1; 386 } 387 if (event & EV_WRITE) { 388 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 389 fatal("msgbuf_write"); 390 if (n == 0) /* connection closed */ 391 shut = 1; 392 } 393 394 for (;;) { 395 if ((n = imsg_get(ibuf, &imsg)) == -1) 396 fatal("imsg_get"); 397 398 if (n == 0) 399 break; 400 401 switch (imsg.hdr.type) { 402 case IMSG_MFC_ADD: 403 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(mfc)) 404 fatalx("invalid size of RDE request"); 405 memcpy(&mfc, imsg.data, sizeof(mfc)); 406 407 /* add to MFC */ 408 mrt_add_mfc(conf->mroute_socket, &mfc); 409 break; 410 case IMSG_MFC_DEL: 411 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(mfc)) 412 fatalx("invalid size of RDE request"); 413 memcpy(&mfc, imsg.data, sizeof(mfc)); 414 415 /* remove from MFC */ 416 mrt_del_mfc(conf->mroute_socket, &mfc); 417 break; 418 default: 419 log_debug("main_dispatch_rde: error handling imsg %d", 420 imsg.hdr.type); 421 break; 422 } 423 imsg_free(&imsg); 424 } 425 if (!shut) 426 imsg_event_add(iev); 427 else { 428 /* this pipe is dead, so remove the event handler */ 429 event_del(&iev->ev); 430 event_loopexit(NULL); 431 } 432 } 433 434 void 435 main_imsg_compose_dvmrpe(int type, pid_t pid, void *data, u_int16_t datalen) 436 { 437 imsg_compose_event(iev_dvmrpe, type, 0, pid, -1, data, datalen); 438 } 439 440 void 441 main_imsg_compose_rde(int type, pid_t pid, void *data, u_int16_t datalen) 442 { 443 imsg_compose_event(iev_rde, type, 0, pid, -1, data, datalen); 444 } 445 446 void 447 imsg_event_add(struct imsgev *iev) 448 { 449 iev->events = EV_READ; 450 if (iev->ibuf.w.queued) 451 iev->events |= EV_WRITE; 452 453 event_del(&iev->ev); 454 event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev); 455 event_add(&iev->ev, NULL); 456 } 457 458 int 459 imsg_compose_event(struct imsgev *iev, u_int16_t type, 460 u_int32_t peerid, pid_t pid, int fd, void *data, u_int16_t datalen) 461 { 462 int ret; 463 464 if ((ret = imsg_compose(&iev->ibuf, type, peerid, 465 pid, fd, data, datalen)) != -1) 466 imsg_event_add(iev); 467 return (ret); 468 } 469