1 /* $OpenBSD: radiusd_module.c,v 1.26 2024/11/21 13:43:10 claudio Exp $ */
2
3 /*
4 * Copyright (c) 2015 YASUOKA Masahiko <yasuoka@yasuoka.net>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 /* radiusd_module.c -- helper functions for radiusd modules */
20
21 #include <sys/types.h>
22 #include <sys/queue.h>
23 #include <sys/uio.h>
24
25 #include <err.h>
26 #include <errno.h>
27 #include <event.h>
28 #include <fcntl.h>
29 #include <imsg.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <syslog.h>
34 #include <unistd.h>
35 #include <pwd.h>
36
37 #include "radiusd.h"
38 #include "radiusd_module.h"
39 #include "imsg_subr.h"
40
41 static void (*module_config_set) (void *, const char *, int,
42 char * const *) = NULL;
43 static void (*module_start_module) (void *) = NULL;
44 static void (*module_stop_module) (void *) = NULL;
45 static void (*module_userpass) (void *, u_int, const char *, const char *)
46 = NULL;
47 static void (*module_access_request) (void *, u_int, const u_char *,
48 size_t) = NULL;
49 static void (*module_next_response) (void *, u_int, const u_char *,
50 size_t) = NULL;
51 static void (*module_request_decoration) (void *, u_int, const u_char *,
52 size_t) = NULL;
53 static void (*module_response_decoration) (void *, u_int, const u_char *,
54 size_t, const u_char *, size_t) = NULL;
55 static void (*module_accounting_request) (void *, u_int, const u_char *,
56 size_t) = NULL;
57 static void (*module_dispatch_control) (void *, struct imsg *) = NULL;
58
59 struct module_base {
60 void *ctx;
61 struct imsgbuf ibuf;
62 bool priv_dropped;
63
64 /* Buffer for receiving the RADIUS packet */
65 u_char *radpkt;
66 int radpktsiz;
67 int radpktoff;
68 u_char *radpkt2;
69 int radpkt2siz; /* allocated size */
70 int radpkt2len; /* actual size */
71
72 #ifdef USE_LIBEVENT
73 struct module_imsgbuf *module_imsgbuf;
74 bool writeready;
75 bool stopped;
76 bool ev_onhandler;
77 struct event ev;
78 #endif
79 };
80
81 static int module_common_radpkt(struct module_base *, uint32_t, u_int,
82 const u_char *, size_t);
83 static int module_recv_imsg(struct module_base *);
84 static int module_imsg_handler(struct module_base *, struct imsg *);
85 #ifdef USE_LIBEVENT
86 static void module_on_event(int, short, void *);
87 #endif
88 static void module_reset_event(struct module_base *);
89
90 struct module_base *
module_create(int sock,void * ctx,struct module_handlers * handler)91 module_create(int sock, void *ctx, struct module_handlers *handler)
92 {
93 struct module_base *base;
94
95 if ((base = calloc(1, sizeof(struct module_base))) == NULL)
96 return (NULL);
97
98 if (imsgbuf_init(&base->ibuf, sock) == -1) {
99 free(base);
100 return (NULL);
101 }
102 base->ctx = ctx;
103
104 module_userpass = handler->userpass;
105 module_access_request = handler->access_request;
106 module_next_response = handler->next_response;
107 module_config_set = handler->config_set;
108 module_request_decoration = handler->request_decoration;
109 module_response_decoration = handler->response_decoration;
110 module_accounting_request = handler->accounting_request;
111 module_start_module = handler->start;
112 module_stop_module = handler->stop;
113 module_dispatch_control = handler->dispatch_control;
114
115 return (base);
116 }
117
118 void
module_start(struct module_base * base)119 module_start(struct module_base *base)
120 {
121 #ifdef USE_LIBEVENT
122 int ival;
123
124 if ((ival = fcntl(base->ibuf.fd, F_GETFL)) == -1)
125 err(1, "Failed to F_GETFL");
126 if (fcntl(base->ibuf.fd, F_SETFL, ival | O_NONBLOCK) == -1)
127 err(1, "Failed to setup NONBLOCK");
128 event_set(&base->ev, base->ibuf.fd, EV_READ, module_on_event, base);
129 event_add(&base->ev, NULL);
130 #endif
131 }
132
133 int
module_run(struct module_base * base)134 module_run(struct module_base *base)
135 {
136 int ret;
137
138 ret = module_recv_imsg(base);
139 if (ret == 0)
140 imsgbuf_flush(&base->ibuf);
141
142 return (ret);
143 }
144
145 void
module_destroy(struct module_base * base)146 module_destroy(struct module_base *base)
147 {
148 if (base != NULL) {
149 free(base->radpkt);
150 free(base->radpkt2);
151 imsgbuf_clear(&base->ibuf);
152 }
153 free(base);
154 }
155
156 void
module_load(struct module_base * base)157 module_load(struct module_base *base)
158 {
159 struct radiusd_module_load_arg load;
160
161 memset(&load, 0, sizeof(load));
162 if (module_userpass != NULL)
163 load.cap |= RADIUSD_MODULE_CAP_USERPASS;
164 if (module_access_request != NULL)
165 load.cap |= RADIUSD_MODULE_CAP_ACCSREQ;
166 if (module_next_response != NULL)
167 load.cap |= RADIUSD_MODULE_CAP_NEXTRES;
168 if (module_request_decoration != NULL)
169 load.cap |= RADIUSD_MODULE_CAP_REQDECO;
170 if (module_response_decoration != NULL)
171 load.cap |= RADIUSD_MODULE_CAP_RESDECO;
172 if (module_accounting_request != NULL)
173 load.cap |= RADIUSD_MODULE_CAP_ACCTREQ;
174 if (module_dispatch_control != NULL)
175 load.cap |= RADIUSD_MODULE_CAP_CONTROL;
176 imsg_compose(&base->ibuf, IMSG_RADIUSD_MODULE_LOAD, 0, 0, -1, &load,
177 sizeof(load));
178 imsgbuf_flush(&base->ibuf);
179 }
180
181 void
module_drop_privilege(struct module_base * base,int nochroot)182 module_drop_privilege(struct module_base *base, int nochroot)
183 {
184 struct passwd *pw;
185
186 tzset();
187
188 /* Drop the privilege */
189 if ((pw = getpwnam(RADIUSD_USER)) == NULL)
190 goto on_fail;
191 if (nochroot == 0 && chroot(pw->pw_dir) == -1)
192 goto on_fail;
193 if (chdir("/") == -1)
194 goto on_fail;
195 if (setgroups(1, &pw->pw_gid) ||
196 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
197 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
198 goto on_fail;
199 base->priv_dropped = true;
200
201 on_fail:
202 return;
203 }
204
205 int
module_notify_secret(struct module_base * base,const char * secret)206 module_notify_secret(struct module_base *base, const char *secret)
207 {
208 int ret;
209
210 ret = imsg_compose(&base->ibuf, IMSG_RADIUSD_MODULE_NOTIFY_SECRET,
211 0, 0, -1, secret, strlen(secret) + 1);
212 module_reset_event(base);
213
214 return (ret);
215 }
216
217 int
module_send_message(struct module_base * base,uint32_t cmd,const char * fmt,...)218 module_send_message(struct module_base *base, uint32_t cmd, const char *fmt,
219 ...)
220 {
221 char *msg;
222 va_list ap;
223 int ret;
224
225 if (fmt == NULL)
226 ret = imsg_compose(&base->ibuf, cmd, 0, 0, -1, NULL, 0);
227 else {
228 va_start(ap, fmt);
229 vasprintf(&msg, fmt, ap);
230 va_end(ap);
231 if (msg == NULL)
232 return (-1);
233 ret = imsg_compose(&base->ibuf, cmd, 0, 0, -1, msg,
234 strlen(msg) + 1);
235 free(msg);
236 }
237 module_reset_event(base);
238
239 return (ret);
240 }
241
242 int
module_userpass_ok(struct module_base * base,u_int q_id,const char * msg)243 module_userpass_ok(struct module_base *base, u_int q_id, const char *msg)
244 {
245 int ret;
246 struct iovec iov[2];
247
248 iov[0].iov_base = &q_id;
249 iov[0].iov_len = sizeof(q_id);
250 iov[1].iov_base = (char *)msg;
251 iov[1].iov_len = strlen(msg) + 1;
252 ret = imsg_composev(&base->ibuf, IMSG_RADIUSD_MODULE_USERPASS_OK,
253 0, 0, -1, iov, 2);
254 module_reset_event(base);
255
256 return (ret);
257 }
258
259 int
module_userpass_fail(struct module_base * base,u_int q_id,const char * msg)260 module_userpass_fail(struct module_base *base, u_int q_id, const char *msg)
261 {
262 int ret;
263 struct iovec iov[2];
264
265 iov[0].iov_base = &q_id;
266 iov[0].iov_len = sizeof(q_id);
267 iov[1].iov_base = (char *)msg;
268 iov[1].iov_len = strlen(msg) + 1;
269 ret = imsg_composev(&base->ibuf, IMSG_RADIUSD_MODULE_USERPASS_FAIL,
270 0, 0, -1, iov, 2);
271 module_reset_event(base);
272
273 return (ret);
274 }
275
276 int
module_accsreq_answer(struct module_base * base,u_int q_id,const u_char * pkt,size_t pktlen)277 module_accsreq_answer(struct module_base *base, u_int q_id, const u_char *pkt,
278 size_t pktlen)
279 {
280 return (module_common_radpkt(base, IMSG_RADIUSD_MODULE_ACCSREQ_ANSWER,
281 q_id, pkt, pktlen));
282 }
283
284 int
module_accsreq_next(struct module_base * base,u_int q_id,const u_char * pkt,size_t pktlen)285 module_accsreq_next(struct module_base *base, u_int q_id, const u_char *pkt,
286 size_t pktlen)
287 {
288 return (module_common_radpkt(base, IMSG_RADIUSD_MODULE_ACCSREQ_NEXT,
289 q_id, pkt, pktlen));
290 }
291
292 int
module_accsreq_aborted(struct module_base * base,u_int q_id)293 module_accsreq_aborted(struct module_base *base, u_int q_id)
294 {
295 int ret;
296
297 ret = imsg_compose(&base->ibuf, IMSG_RADIUSD_MODULE_ACCSREQ_ABORTED,
298 0, 0, -1, &q_id, sizeof(u_int));
299 module_reset_event(base);
300
301 return (ret);
302 }
303
304 int
module_reqdeco_done(struct module_base * base,u_int q_id,const u_char * pkt,size_t pktlen)305 module_reqdeco_done(struct module_base *base, u_int q_id, const u_char *pkt,
306 size_t pktlen)
307 {
308 return (module_common_radpkt(base, IMSG_RADIUSD_MODULE_REQDECO_DONE,
309 q_id, pkt, pktlen));
310 }
311
312 int
module_resdeco_done(struct module_base * base,u_int q_id,const u_char * pkt,size_t pktlen)313 module_resdeco_done(struct module_base *base, u_int q_id, const u_char *pkt,
314 size_t pktlen)
315 {
316 return (module_common_radpkt(base, IMSG_RADIUSD_MODULE_RESDECO_DONE,
317 q_id, pkt, pktlen));
318 }
319
320 static int
module_common_radpkt(struct module_base * base,uint32_t imsg_type,u_int q_id,const u_char * pkt,size_t pktlen)321 module_common_radpkt(struct module_base *base, uint32_t imsg_type, u_int q_id,
322 const u_char *pkt, size_t pktlen)
323 {
324 int ret = 0, off = 0, len, siz;
325 struct iovec iov[2];
326 struct radiusd_module_radpkt_arg ans;
327
328 len = pktlen;
329 ans.q_id = q_id;
330 ans.pktlen = pktlen;
331 ans.final = false;
332
333 while (!ans.final) {
334 siz = MAX_IMSGSIZE - sizeof(ans);
335 if (len - off <= siz) {
336 ans.final = true;
337 siz = len - off;
338 }
339 iov[0].iov_base = &ans;
340 iov[0].iov_len = sizeof(ans);
341 if (siz > 0) {
342 iov[1].iov_base = (u_char *)pkt + off;
343 iov[1].iov_len = siz;
344 }
345 ret = imsg_composev(&base->ibuf, imsg_type, 0, 0, -1, iov,
346 (siz > 0)? 2 : 1);
347 if (ret == -1)
348 break;
349 off += siz;
350 }
351 module_reset_event(base);
352
353 return (ret);
354 }
355
356 static int
module_recv_imsg(struct module_base * base)357 module_recv_imsg(struct module_base *base)
358 {
359 ssize_t n;
360 struct imsg imsg;
361
362 if ((n = imsgbuf_read(&base->ibuf)) != 1) {
363 if (n == -1)
364 syslog(LOG_ERR, "%s: imsgbuf_read(): %m", __func__);
365 module_stop(base);
366 return (-1);
367 }
368 for (;;) {
369 if ((n = imsg_get(&base->ibuf, &imsg)) == -1) {
370 syslog(LOG_ERR, "%s: imsg_get(): %m", __func__);
371 module_stop(base);
372 return (-1);
373 }
374 if (n == 0)
375 break;
376 module_imsg_handler(base, &imsg);
377 imsg_free(&imsg);
378 }
379 module_reset_event(base);
380
381 return (0);
382 }
383
384 static int
module_imsg_handler(struct module_base * base,struct imsg * imsg)385 module_imsg_handler(struct module_base *base, struct imsg *imsg)
386 {
387 ssize_t datalen;
388
389 datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
390 switch (imsg->hdr.type) {
391 case IMSG_RADIUSD_MODULE_SET_CONFIG:
392 {
393 struct radiusd_module_set_arg *arg;
394 struct radiusd_module_object *val;
395 u_int i;
396 size_t off;
397 char **argv;
398
399 arg = (struct radiusd_module_set_arg *)imsg->data;
400 off = sizeof(struct radiusd_module_set_arg);
401
402 if ((argv = calloc(sizeof(const char *), arg->nparamval))
403 == NULL) {
404 module_send_message(base, IMSG_NG,
405 "Out of memory: %s", strerror(errno));
406 break;
407 }
408 for (i = 0; i < arg->nparamval; i++) {
409 if (datalen - off <
410 sizeof(struct radiusd_module_object))
411 break;
412 val = (struct radiusd_module_object *)
413 ((caddr_t)imsg->data + off);
414 if (datalen - off < val->size)
415 break;
416 argv[i] = (char *)(val + 1);
417 off += val->size;
418 }
419 if (i >= arg->nparamval)
420 module_config_set(base->ctx, arg->paramname,
421 arg->nparamval, argv);
422 else
423 module_send_message(base, IMSG_NG,
424 "Internal protocol error");
425 free(argv);
426
427 break;
428 }
429 case IMSG_RADIUSD_MODULE_START:
430 if (module_start_module != NULL) {
431 module_start_module(base->ctx);
432 if (!base->priv_dropped) {
433 syslog(LOG_ERR, "Module tried to start with "
434 "root privileges");
435 abort();
436 }
437 } else {
438 if (!base->priv_dropped) {
439 syslog(LOG_ERR, "Module tried to start with "
440 "root privileges");
441 abort();
442 }
443 module_send_message(base, IMSG_OK, NULL);
444 }
445 break;
446 case IMSG_RADIUSD_MODULE_STOP:
447 module_stop(base);
448 break;
449 case IMSG_RADIUSD_MODULE_USERPASS:
450 {
451 struct radiusd_module_userpass_arg *userpass;
452
453 if (module_userpass == NULL) {
454 syslog(LOG_ERR, "Received USERPASS message, but "
455 "module doesn't support");
456 break;
457 }
458 if (datalen <
459 (ssize_t)sizeof(struct radiusd_module_userpass_arg)) {
460 syslog(LOG_ERR, "Received USERPASS message, but "
461 "length is wrong");
462 break;
463 }
464 userpass = (struct radiusd_module_userpass_arg *)imsg->data;
465 module_userpass(base->ctx, userpass->q_id, userpass->user,
466 (userpass->has_pass)? userpass->pass : NULL);
467 explicit_bzero(userpass,
468 sizeof(struct radiusd_module_userpass_arg));
469 break;
470 }
471 case IMSG_RADIUSD_MODULE_ACCSREQ:
472 case IMSG_RADIUSD_MODULE_NEXTRES:
473 case IMSG_RADIUSD_MODULE_REQDECO:
474 case IMSG_RADIUSD_MODULE_RESDECO0_REQ:
475 case IMSG_RADIUSD_MODULE_RESDECO:
476 case IMSG_RADIUSD_MODULE_ACCTREQ:
477 {
478 struct radiusd_module_radpkt_arg *accessreq;
479 int chunklen;
480 const char *typestr;
481
482 if (imsg->hdr.type == IMSG_RADIUSD_MODULE_ACCSREQ) {
483 if (module_access_request == NULL) {
484 syslog(LOG_ERR, "Received ACCSREQ message, but "
485 "module doesn't support");
486 break;
487 }
488 typestr = "ACCSREQ";
489 } else if (imsg->hdr.type == IMSG_RADIUSD_MODULE_NEXTRES) {
490 if (module_next_response == NULL) {
491 syslog(LOG_ERR, "Received NEXTRES message, but "
492 "module doesn't support");
493 break;
494 }
495 typestr = "NEXTRES";
496 } else if (imsg->hdr.type == IMSG_RADIUSD_MODULE_ACCTREQ) {
497 if (module_accounting_request == NULL) {
498 syslog(LOG_ERR, "Received ACCTREQ message, but "
499 "module doesn't support");
500 break;
501 }
502 typestr = "ACCTREQ";
503 } else if (imsg->hdr.type == IMSG_RADIUSD_MODULE_REQDECO) {
504 if (module_request_decoration == NULL) {
505 syslog(LOG_ERR, "Received REQDECO message, but "
506 "module doesn't support");
507 break;
508 }
509 typestr = "REQDECO";
510 } else {
511 if (module_response_decoration == NULL) {
512 syslog(LOG_ERR, "Received RESDECO message, but "
513 "module doesn't support");
514 break;
515 }
516 if (imsg->hdr.type == IMSG_RADIUSD_MODULE_RESDECO0_REQ)
517 typestr = "RESDECO0_REQ";
518 else
519 typestr = "RESDECO";
520 }
521
522 if (datalen <
523 (ssize_t)sizeof(struct radiusd_module_radpkt_arg)) {
524 syslog(LOG_ERR, "Received %s message, but "
525 "length is wrong", typestr);
526 break;
527 }
528 accessreq = (struct radiusd_module_radpkt_arg *)imsg->data;
529 if (base->radpktsiz < accessreq->pktlen) {
530 u_char *nradpkt;
531 if ((nradpkt = realloc(base->radpkt,
532 accessreq->pktlen)) == NULL) {
533 syslog(LOG_ERR, "Could not handle received "
534 "%s message: %m", typestr);
535 base->radpktoff = 0;
536 goto accsreq_out;
537 }
538 base->radpkt = nradpkt;
539 base->radpktsiz = accessreq->pktlen;
540 }
541 chunklen = datalen - sizeof(struct radiusd_module_radpkt_arg);
542 if (chunklen > base->radpktsiz - base->radpktoff){
543 syslog(LOG_ERR,
544 "Could not handle received %s message: "
545 "received length is too big", typestr);
546 base->radpktoff = 0;
547 goto accsreq_out;
548 }
549 memcpy(base->radpkt + base->radpktoff,
550 (caddr_t)(accessreq + 1), chunklen);
551 base->radpktoff += chunklen;
552 if (!accessreq->final)
553 goto accsreq_out;
554 if (base->radpktoff != accessreq->pktlen) {
555 syslog(LOG_ERR,
556 "Could not handle received %s "
557 "message: length is mismatch", typestr);
558 base->radpktoff = 0;
559 goto accsreq_out;
560 }
561 if (imsg->hdr.type == IMSG_RADIUSD_MODULE_ACCSREQ)
562 module_access_request(base->ctx, accessreq->q_id,
563 base->radpkt, base->radpktoff);
564 else if (imsg->hdr.type == IMSG_RADIUSD_MODULE_NEXTRES)
565 module_next_response(base->ctx, accessreq->q_id,
566 base->radpkt, base->radpktoff);
567 else if (imsg->hdr.type == IMSG_RADIUSD_MODULE_REQDECO)
568 module_request_decoration(base->ctx, accessreq->q_id,
569 base->radpkt, base->radpktoff);
570 else if (imsg->hdr.type == IMSG_RADIUSD_MODULE_RESDECO0_REQ) {
571 /* preserve request */
572 if (base->radpktoff > base->radpkt2siz) {
573 u_char *nradpkt;
574 if ((nradpkt = realloc(base->radpkt2,
575 base->radpktoff)) == NULL) {
576 syslog(LOG_ERR, "Could not handle "
577 "received %s message: %m", typestr);
578 base->radpktoff = 0;
579 goto accsreq_out;
580 }
581 base->radpkt2 = nradpkt;
582 base->radpkt2siz = base->radpktoff;
583 }
584 memcpy(base->radpkt2, base->radpkt, base->radpktoff);
585 base->radpkt2len = base->radpktoff;
586 } else if (imsg->hdr.type == IMSG_RADIUSD_MODULE_RESDECO) {
587 module_response_decoration(base->ctx, accessreq->q_id,
588 base->radpkt2, base->radpkt2len, base->radpkt,
589 base->radpktoff);
590 base->radpkt2len = 0;
591 } else
592 module_accounting_request(base->ctx, accessreq->q_id,
593 base->radpkt, base->radpktoff);
594 base->radpktoff = 0;
595 accsreq_out:
596 break;
597 }
598 case IMSG_RADIUSD_MODULE_CTRL_UNBIND:
599 goto forward_msg;
600 break;
601 default:
602 if (imsg->hdr.type >= IMSG_RADIUSD_MODULE_MIN) {
603 forward_msg:
604 if (module_dispatch_control == NULL) {
605 const char msg[] =
606 "the module doesn't handle any controls";
607 imsg_compose(&base->ibuf, IMSG_NG,
608 imsg->hdr.peerid, 0, -1, msg, sizeof(msg));
609 } else
610 module_dispatch_control(base->ctx, imsg);
611 }
612 }
613
614 return (0);
615 }
616
617 void
module_stop(struct module_base * base)618 module_stop(struct module_base *base)
619 {
620 if (module_stop_module != NULL)
621 module_stop_module(base->ctx);
622 #ifdef USE_LIBEVENT
623 event_del(&base->ev);
624 base->stopped = true;
625 #endif
626 close(base->ibuf.fd);
627 }
628
629 #ifdef USE_LIBEVENT
630 static void
module_on_event(int fd,short evmask,void * ctx)631 module_on_event(int fd, short evmask, void *ctx)
632 {
633 struct module_base *base = ctx;
634 int ret;
635
636 base->ev_onhandler = true;
637 if (evmask & EV_WRITE) {
638 base->writeready = true;
639 if (imsgbuf_write(&base->ibuf) == -1) {
640 syslog(LOG_ERR, "%s: imsgbuf_write: %m", __func__);
641 module_stop(base);
642 return;
643 }
644 base->writeready = false;
645 }
646 if (evmask & EV_READ) {
647 ret = module_recv_imsg(base);
648 if (ret < 0)
649 return;
650 }
651 base->ev_onhandler = false;
652 module_reset_event(base);
653 return;
654 }
655 #endif
656
657 static void
module_reset_event(struct module_base * base)658 module_reset_event(struct module_base *base)
659 {
660 #ifdef USE_LIBEVENT
661 short evmask = 0;
662 struct timeval *tvp = NULL, tv = { 0, 0 };
663
664 if (base->ev_onhandler)
665 return;
666 if (base->stopped)
667 return;
668 event_del(&base->ev);
669
670 evmask |= EV_READ;
671 if (imsgbuf_queuelen(&base->ibuf) > 0) {
672 if (!base->writeready)
673 evmask |= EV_WRITE;
674 else
675 tvp = &tv; /* fire immediately */
676 }
677 event_set(&base->ev, base->ibuf.fd, evmask, module_on_event, base);
678 if (event_add(&base->ev, tvp) == -1)
679 syslog(LOG_ERR, "event_add() failed in %s()", __func__);
680 #endif
681 }
682
683 int
module_imsg_compose(struct module_base * base,uint32_t type,uint32_t id,pid_t pid,int fd,const void * data,size_t datalen)684 module_imsg_compose(struct module_base *base, uint32_t type, uint32_t id,
685 pid_t pid, int fd, const void *data, size_t datalen)
686 {
687 int ret;
688
689 if ((ret = imsg_compose(&base->ibuf, type, id, pid, fd, data, datalen))
690 != -1)
691 module_reset_event(base);
692
693 return (ret);
694 }
695
696 int
module_imsg_composev(struct module_base * base,uint32_t type,uint32_t id,pid_t pid,int fd,const struct iovec * iov,int iovcnt)697 module_imsg_composev(struct module_base *base, uint32_t type, uint32_t id,
698 pid_t pid, int fd, const struct iovec *iov, int iovcnt)
699 {
700 int ret;
701
702 if ((ret = imsg_composev(&base->ibuf, type, id, pid, fd, iov, iovcnt))
703 != -1)
704 module_reset_event(base);
705
706 return (ret);
707 }
708