1 /* $OpenBSD: dvmrpd.c,v 1.25 2016/09/02 16:20:34 benno 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 struct imsgev *iev_dvmrpe; 66 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 dvmrpd_process = PROC_MAIN; 112 log_procname = log_procnames[dvmrpd_process]; 113 114 log_init(1); /* log to stderr until daemonized */ 115 log_verbose(1); 116 117 while ((ch = getopt(argc, argv, "df:nv")) != -1) { 118 switch (ch) { 119 case 'd': 120 debug = 1; 121 break; 122 case 'f': 123 conffile = optarg; 124 break; 125 case 'n': 126 opts |= DVMRPD_OPT_NOACTION; 127 break; 128 case 'v': 129 if (opts & DVMRPD_OPT_VERBOSE) 130 opts |= DVMRPD_OPT_VERBOSE2; 131 opts |= DVMRPD_OPT_VERBOSE; 132 log_verbose(1); 133 break; 134 default: 135 usage(); 136 /* NOTREACHED */ 137 } 138 } 139 140 argc -= optind; 141 argv += optind; 142 if (argc > 0) 143 usage(); 144 145 log_init(debug); 146 log_verbose(opts & DVMRPD_OPT_VERBOSE); 147 148 /* multicast IP forwarding must be enabled */ 149 mib[0] = CTL_NET; 150 mib[1] = PF_INET; 151 mib[2] = IPPROTO_IP; 152 mib[3] = IPCTL_MFORWARDING; 153 len = sizeof(ipmforwarding); 154 if (sysctl(mib, 4, &ipmforwarding, &len, NULL, 0) == -1) 155 err(1, "sysctl"); 156 157 if (!ipmforwarding) 158 errx(1, "multicast IP forwarding not enabled"); 159 160 /* fetch interfaces early */ 161 kif_init(); 162 163 /* parse config file */ 164 if ((conf = parse_config(conffile, opts)) == NULL ) 165 exit(1); 166 167 if (conf->opts & DVMRPD_OPT_NOACTION) { 168 if (conf->opts & DVMRPD_OPT_VERBOSE) 169 print_config(conf); 170 else 171 fprintf(stderr, "configuration OK\n"); 172 exit(0); 173 } 174 175 /* check for root privileges */ 176 if (geteuid()) 177 errx(1, "need root privileges"); 178 179 /* check for dvmrpd user */ 180 if (getpwnam(DVMRPD_USER) == NULL) 181 errx(1, "unknown user %s", DVMRPD_USER); 182 183 /* start logging */ 184 log_init(1); 185 186 if (!debug) 187 daemon(1, 0); 188 189 log_info("startup"); 190 191 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 192 PF_UNSPEC, pipe_parent2dvmrpe) == -1) 193 fatal("socketpair"); 194 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 195 PF_UNSPEC, pipe_parent2rde) == -1) 196 fatal("socketpair"); 197 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 198 PF_UNSPEC, pipe_dvmrpe2rde) == -1) 199 fatal("socketpair"); 200 201 /* start children */ 202 rde_pid = rde(conf, pipe_parent2rde, pipe_dvmrpe2rde, 203 pipe_parent2dvmrpe); 204 dvmrpe_pid = dvmrpe(conf, pipe_parent2dvmrpe, pipe_dvmrpe2rde, 205 pipe_parent2rde); 206 207 /* create the raw ip socket */ 208 if ((conf->mroute_socket = socket(AF_INET, 209 SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, 210 IPPROTO_IGMP)) == -1) 211 fatal("error creating raw socket"); 212 213 if_set_recvbuf(conf->mroute_socket); 214 215 if (mrt_init(conf->mroute_socket)) 216 fatal("multicast routing not enabled in kernel"); 217 218 event_init(); 219 220 /* setup signal handler */ 221 signal_set(&ev_sigint, SIGINT, main_sig_handler, NULL); 222 signal_set(&ev_sigterm, SIGTERM, main_sig_handler, NULL); 223 signal_set(&ev_sighup, SIGHUP, main_sig_handler, NULL); 224 signal_add(&ev_sigint, NULL); 225 signal_add(&ev_sigterm, NULL); 226 signal_add(&ev_sighup, NULL); 227 signal(SIGPIPE, SIG_IGN); 228 229 /* setup pipes to children */ 230 close(pipe_parent2dvmrpe[1]); 231 close(pipe_parent2rde[1]); 232 close(pipe_dvmrpe2rde[0]); 233 close(pipe_dvmrpe2rde[1]); 234 235 if ((iev_dvmrpe = malloc(sizeof(struct imsgev))) == NULL || 236 (iev_rde = malloc(sizeof(struct imsgev))) == NULL) 237 fatal(NULL); 238 imsg_init(&iev_dvmrpe->ibuf, pipe_parent2dvmrpe[0]); 239 imsg_init(&iev_rde->ibuf, pipe_parent2rde[0]); 240 iev_dvmrpe->handler = main_dispatch_dvmrpe; 241 iev_rde->handler = main_dispatch_rde; 242 243 /* setup event handler */ 244 iev_dvmrpe->events = EV_READ; 245 event_set(&iev_dvmrpe->ev, iev_dvmrpe->ibuf.fd, iev_dvmrpe->events, 246 iev_dvmrpe->handler, iev_dvmrpe); 247 event_add(&iev_dvmrpe->ev, NULL); 248 249 iev_rde->events = EV_READ; 250 event_set(&iev_rde->ev, iev_rde->ibuf.fd, iev_rde->events, 251 iev_rde->handler, iev_rde); 252 event_add(&iev_rde->ev, NULL); 253 254 if (kmr_init(!(conf->flags & DVMRPD_FLAG_NO_FIB_UPDATE)) == -1) 255 dvmrpd_shutdown(); 256 if (kr_init() == -1) 257 dvmrpd_shutdown(); 258 259 event_set(&conf->ev, conf->mroute_socket, EV_READ|EV_PERSIST, 260 kmr_recv_msg, conf); 261 event_add(&conf->ev, NULL); 262 263 event_dispatch(); 264 265 dvmrpd_shutdown(); 266 /* NOTREACHED */ 267 return (0); 268 } 269 270 __dead void 271 dvmrpd_shutdown(void) 272 { 273 struct iface *iface; 274 pid_t pid; 275 int status; 276 277 /* close pipes */ 278 msgbuf_clear(&iev_dvmrpe->ibuf.w); 279 close(iev_dvmrpe->ibuf.fd); 280 msgbuf_clear(&iev_rde->ibuf.w); 281 close(iev_rde->ibuf.fd); 282 283 control_cleanup(); 284 kmr_shutdown(); 285 kr_shutdown(); 286 LIST_FOREACH(iface, &conf->iface_list, entry) { 287 if_del(iface); 288 } 289 mrt_done(conf->mroute_socket); 290 291 log_debug("waiting for children to terminate"); 292 do { 293 pid = wait(&status); 294 if (pid == -1) { 295 if (errno != EINTR && errno != ECHILD) 296 fatal("wait"); 297 } else if (WIFSIGNALED(status)) 298 log_warnx("%s terminated; signal %d", 299 (pid == rde_pid) ? "route decision engine" : 300 "dvmrp engine", WTERMSIG(status)); 301 } while (pid != -1 || (pid == -1 && errno == EINTR)); 302 303 free(iev_dvmrpe); 304 free(iev_rde); 305 306 log_info("terminating"); 307 exit(0); 308 } 309 310 /* imsg handling */ 311 void 312 main_dispatch_dvmrpe(int fd, short event, void *bula) 313 { 314 struct imsgev *iev = bula; 315 struct imsgbuf *ibuf = &iev->ibuf; 316 struct imsg imsg; 317 ssize_t n; 318 int shut = 0, verbose; 319 320 if (event & EV_READ) { 321 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 322 fatal("imsg_read error"); 323 if (n == 0) /* connection closed */ 324 shut = 1; 325 } 326 if (event & EV_WRITE) { 327 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 328 fatal("msgbuf_write"); 329 if (n == 0) /* connection closed */ 330 shut = 1; 331 } 332 333 for (;;) { 334 if ((n = imsg_get(ibuf, &imsg)) == -1) 335 fatal("imsg_get"); 336 337 if (n == 0) 338 break; 339 340 switch (imsg.hdr.type) { 341 case IMSG_CTL_RELOAD: 342 log_debug("main_dispatch_dvmrpe: IMSG_CTL_RELOAD"); 343 /* reconfig */ 344 break; 345 case IMSG_CTL_MFC_COUPLE: 346 kmr_mfc_couple(); 347 break; 348 case IMSG_CTL_MFC_DECOUPLE: 349 kmr_mfc_decouple(); 350 break; 351 case IMSG_CTL_LOG_VERBOSE: 352 /* already checked by dvmrpe */ 353 memcpy(&verbose, imsg.data, sizeof(verbose)); 354 log_verbose(verbose); 355 break; 356 default: 357 log_debug("main_dispatch_dvmrpe: error handling " 358 "imsg %d", imsg.hdr.type); 359 break; 360 } 361 imsg_free(&imsg); 362 } 363 if (!shut) 364 imsg_event_add(iev); 365 else { 366 /* this pipe is dead, so remove the event handler */ 367 event_del(&iev->ev); 368 event_loopexit(NULL); 369 } 370 } 371 372 void 373 main_dispatch_rde(int fd, short event, void *bula) 374 { 375 struct mfc mfc; 376 struct imsgev *iev = bula; 377 struct imsgbuf *ibuf = &iev->ibuf; 378 struct imsg imsg; 379 ssize_t n; 380 int shut = 0; 381 382 if (event & EV_READ) { 383 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN) 384 fatal("imsg_read error"); 385 if (n == 0) /* connection closed */ 386 shut = 1; 387 } 388 if (event & EV_WRITE) { 389 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 390 fatal("msgbuf_write"); 391 if (n == 0) /* connection closed */ 392 shut = 1; 393 } 394 395 for (;;) { 396 if ((n = imsg_get(ibuf, &imsg)) == -1) 397 fatal("imsg_get"); 398 399 if (n == 0) 400 break; 401 402 switch (imsg.hdr.type) { 403 case IMSG_MFC_ADD: 404 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(mfc)) 405 fatalx("invalid size of RDE request"); 406 memcpy(&mfc, imsg.data, sizeof(mfc)); 407 408 /* add to MFC */ 409 mrt_add_mfc(conf->mroute_socket, &mfc); 410 break; 411 case IMSG_MFC_DEL: 412 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(mfc)) 413 fatalx("invalid size of RDE request"); 414 memcpy(&mfc, imsg.data, sizeof(mfc)); 415 416 /* remove from MFC */ 417 mrt_del_mfc(conf->mroute_socket, &mfc); 418 break; 419 default: 420 log_debug("main_dispatch_rde: error handling imsg %d", 421 imsg.hdr.type); 422 break; 423 } 424 imsg_free(&imsg); 425 } 426 if (!shut) 427 imsg_event_add(iev); 428 else { 429 /* this pipe is dead, so remove the event handler */ 430 event_del(&iev->ev); 431 event_loopexit(NULL); 432 } 433 } 434 435 void 436 main_imsg_compose_dvmrpe(int type, pid_t pid, void *data, u_int16_t datalen) 437 { 438 imsg_compose_event(iev_dvmrpe, type, 0, pid, -1, data, datalen); 439 } 440 441 void 442 main_imsg_compose_rde(int type, pid_t pid, void *data, u_int16_t datalen) 443 { 444 imsg_compose_event(iev_rde, type, 0, pid, -1, data, datalen); 445 } 446 447 void 448 imsg_event_add(struct imsgev *iev) 449 { 450 iev->events = EV_READ; 451 if (iev->ibuf.w.queued) 452 iev->events |= EV_WRITE; 453 454 event_del(&iev->ev); 455 event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev); 456 event_add(&iev->ev, NULL); 457 } 458 459 int 460 imsg_compose_event(struct imsgev *iev, u_int16_t type, 461 u_int32_t peerid, pid_t pid, int fd, void *data, u_int16_t datalen) 462 { 463 int ret; 464 465 if ((ret = imsg_compose(&iev->ibuf, type, peerid, 466 pid, fd, data, datalen)) != -1) 467 imsg_event_add(iev); 468 return (ret); 469 } 470