| File: | src/usr.sbin/dvmrpd/dvmrpd.c |
| Warning: | line 207, column 27 Access to field 'mroute_socket' results in a dereference of a null pointer (loaded from variable 'conf') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 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(*__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__attribute__((__noreturn__)) void usage(void); | |||
| 53 | __dead__attribute__((__noreturn__)) 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((void *)0); | |||
| 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 SIGTERM15: | |||
| 77 | case SIGINT2: | |||
| 78 | dvmrpd_shutdown(); | |||
| 79 | /* NOTREACHED */ | |||
| 80 | case SIGHUP1: | |||
| 81 | /* reconfigure */ | |||
| 82 | /* ... */ | |||
| 83 | break; | |||
| 84 | default: | |||
| 85 | fatalx("unexpected signal"); | |||
| 86 | /* NOTREACHED */ | |||
| 87 | } | |||
| 88 | } | |||
| 89 | ||||
| 90 | __dead__attribute__((__noreturn__)) void | |||
| 91 | usage(void) | |||
| 92 | { | |||
| 93 | extern char *__progname; | |||
| 94 | ||||
| 95 | fprintf(stderr(&__sF[2]), "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"/etc/dvmrpd.conf"; | |||
| 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_NOACTION0x00000004; | |||
| 126 | break; | |||
| 127 | case 'v': | |||
| 128 | if (opts & DVMRPD_OPT_VERBOSE0x00000001) | |||
| 129 | opts |= DVMRPD_OPT_VERBOSE20x00000002; | |||
| 130 | opts |= DVMRPD_OPT_VERBOSE0x00000001; | |||
| 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_VERBOSE0x00000001); | |||
| 146 | ||||
| 147 | /* multicast IP forwarding must be enabled */ | |||
| 148 | mib[0] = CTL_NET4; | |||
| 149 | mib[1] = PF_INET2; | |||
| 150 | mib[2] = IPPROTO_IP0; | |||
| 151 | mib[3] = IPCTL_MFORWARDING31; | |||
| 152 | len = sizeof(ipmforwarding); | |||
| 153 | if (sysctl(mib, 4, &ipmforwarding, &len, NULL((void *)0), 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((void *)0) ) | |||
| 164 | exit(1); | |||
| 165 | ||||
| 166 | if (conf->opts & DVMRPD_OPT_NOACTION0x00000004) { | |||
| 167 | if (conf->opts & DVMRPD_OPT_VERBOSE0x00000001) | |||
| 168 | print_config(conf); | |||
| 169 | else | |||
| 170 | fprintf(stderr(&__sF[2]), "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"_dvmrpd") == NULL((void *)0)) | |||
| 180 | errx(1, "unknown user %s", DVMRPD_USER"_dvmrpd"); | |||
| 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_UNIX1, SOCK_STREAM1 | SOCK_CLOEXEC0x8000 | SOCK_NONBLOCK0x4000, | |||
| 191 | PF_UNSPEC0, pipe_parent2dvmrpe) == -1) | |||
| 192 | fatal("socketpair"); | |||
| 193 | if (socketpair(AF_UNIX1, SOCK_STREAM1 | SOCK_CLOEXEC0x8000 | SOCK_NONBLOCK0x4000, | |||
| 194 | PF_UNSPEC0, pipe_parent2rde) == -1) | |||
| 195 | fatal("socketpair"); | |||
| 196 | if (socketpair(AF_UNIX1, SOCK_STREAM1 | SOCK_CLOEXEC0x8000 | SOCK_NONBLOCK0x4000, | |||
| 197 | PF_UNSPEC0, 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_INET2, | |||
| ||||
| 208 | SOCK_RAW3 | SOCK_CLOEXEC0x8000 | SOCK_NONBLOCK0x4000, | |||
| 209 | IPPROTO_IGMP2)) == -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)event_set(&ev_sigint, 2, 0x08|0x10, main_sig_handler, ((void *)0)); | |||
| 221 | signal_set(&ev_sigterm, SIGTERM, main_sig_handler, NULL)event_set(&ev_sigterm, 15, 0x08|0x10, main_sig_handler, ( (void *)0)); | |||
| 222 | signal_set(&ev_sighup, SIGHUP, main_sig_handler, NULL)event_set(&ev_sighup, 1, 0x08|0x10, main_sig_handler, ((void *)0)); | |||
| 223 | signal_add(&ev_sigint, NULL)event_add(&ev_sigint, ((void *)0)); | |||
| 224 | signal_add(&ev_sigterm, NULL)event_add(&ev_sigterm, ((void *)0)); | |||
| 225 | signal_add(&ev_sighup, NULL)event_add(&ev_sighup, ((void *)0)); | |||
| 226 | signal(SIGPIPE13, SIG_IGN(void (*)(int))1); | |||
| 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((void *)0) || | |||
| 235 | (iev_rde = malloc(sizeof(struct imsgev))) == NULL((void *)0)) | |||
| 236 | fatal(NULL((void *)0)); | |||
| 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_READ0x02; | |||
| 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((void *)0)); | |||
| 247 | ||||
| 248 | iev_rde->events = EV_READ0x02; | |||
| 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((void *)0)); | |||
| 252 | ||||
| 253 | if (kmr_init(!(conf->flags & DVMRPD_FLAG_NO_FIB_UPDATE0x0001)) == -1) | |||
| 254 | dvmrpd_shutdown(); | |||
| 255 | if (kr_init() == -1) | |||
| 256 | dvmrpd_shutdown(); | |||
| 257 | ||||
| 258 | event_set(&conf->ev, conf->mroute_socket, EV_READ0x02|EV_PERSIST0x10, | |||
| 259 | kmr_recv_msg, conf); | |||
| 260 | event_add(&conf->ev, NULL((void *)0)); | |||
| 261 | ||||
| 262 | event_dispatch(); | |||
| 263 | ||||
| 264 | dvmrpd_shutdown(); | |||
| 265 | /* NOTREACHED */ | |||
| 266 | return (0); | |||
| 267 | } | |||
| 268 | ||||
| 269 | __dead__attribute__((__noreturn__)) 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)for((iface) = ((&conf->iface_list)->lh_first); (iface )!= ((void *)0); (iface) = ((iface)->entry.le_next)) { | |||
| 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(*__errno()) != EINTR4 && errno(*__errno()) != ECHILD10) | |||
| 295 | fatal("wait"); | |||
| 296 | } else if (WIFSIGNALED(status)(((status) & 0177) != 0177 && ((status) & 0177 ) != 0)) | |||
| 297 | log_warnx("%s terminated; signal %d", | |||
| 298 | (pid == rde_pid) ? "route decision engine" : | |||
| 299 | "dvmrp engine", WTERMSIG(status)(((status) & 0177))); | |||
| 300 | } while (pid != -1 || (pid == -1 && errno(*__errno()) == EINTR4)); | |||
| 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_READ0x02) { | |||
| 320 | if ((n = imsg_read(ibuf)) == -1 && errno(*__errno()) != EAGAIN35) | |||
| 321 | fatal("imsg_read error"); | |||
| 322 | if (n == 0) /* connection closed */ | |||
| 323 | shut = 1; | |||
| 324 | } | |||
| 325 | if (event & EV_WRITE0x04) { | |||
| 326 | if ((n = msgbuf_write(&ibuf->w)) == -1 && errno(*__errno()) != EAGAIN35) | |||
| 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((void *)0)); | |||
| 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_READ0x02) { | |||
| 382 | if ((n = imsg_read(ibuf)) == -1 && errno(*__errno()) != EAGAIN35) | |||
| 383 | fatal("imsg_read error"); | |||
| 384 | if (n == 0) /* connection closed */ | |||
| 385 | shut = 1; | |||
| 386 | } | |||
| 387 | if (event & EV_WRITE0x04) { | |||
| 388 | if ((n = msgbuf_write(&ibuf->w)) == -1 && errno(*__errno()) != EAGAIN35) | |||
| 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_SIZEsizeof(struct imsg_hdr) != 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_SIZEsizeof(struct imsg_hdr) != 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((void *)0)); | |||
| 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_READ0x02; | |||
| 450 | if (iev->ibuf.w.queued) | |||
| 451 | iev->events |= EV_WRITE0x04; | |||
| 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((void *)0)); | |||
| 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 | } |