struct buf * imsg_create(struct imsgbuf *ibuf, enum imsg_type type, u_int32_t peerid, pid_t pid, u_int16_t datalen) { struct buf *wbuf; struct imsg_hdr hdr; if (datalen > MAX_IMSGSIZE - IMSG_HEADER_SIZE) { log_warnx("imsg_create: len %u > MAX_IMSGSIZE; " "type %u peerid %lu", datalen + IMSG_HEADER_SIZE, type, peerid); return (NULL); } hdr.len = datalen + IMSG_HEADER_SIZE; hdr.type = type; hdr.peerid = peerid; hdr.pid = pid; if ((wbuf = buf_open(hdr.len)) == NULL) { log_warn("imsg_create: buf_open"); return (NULL); } if (imsg_add(wbuf, &hdr, sizeof(hdr)) == -1) return (NULL); return (wbuf); }
void dispatch_imsg(struct interface_info *ifi, int fd) { struct imsg_hdr hdr; char *medium, *reason, *filename, *servername, *prefix; size_t medium_len, reason_len, filename_len, servername_len, prefix_len, totlen; struct client_lease lease; int ret, i, optlen; struct buf *buf; buf_read(fd, &hdr, sizeof(hdr)); switch (hdr.code) { case IMSG_SCRIPT_INIT: if (hdr.len < sizeof(hdr) + sizeof(size_t)) error("corrupted message received"); buf_read(fd, &medium_len, sizeof(medium_len)); if (hdr.len < medium_len + sizeof(size_t) + sizeof(hdr) + sizeof(size_t) || medium_len == SIZE_T_MAX) error("corrupted message received"); if (medium_len > 0) { if ((medium = calloc(1, medium_len + 1)) == NULL) error("%m"); buf_read(fd, medium, medium_len); } else medium = NULL; buf_read(fd, &reason_len, sizeof(reason_len)); if (hdr.len < medium_len + reason_len + sizeof(hdr) || reason_len == SIZE_T_MAX) error("corrupted message received"); if (reason_len > 0) { if ((reason = calloc(1, reason_len + 1)) == NULL) error("%m"); buf_read(fd, reason, reason_len); } else reason = NULL; priv_script_init(reason, medium); free(reason); free(medium); break; case IMSG_SCRIPT_WRITE_PARAMS: bzero(&lease, sizeof lease); totlen = sizeof(hdr) + sizeof(lease) + sizeof(size_t); if (hdr.len < totlen) error("corrupted message received"); buf_read(fd, &lease, sizeof(lease)); buf_read(fd, &filename_len, sizeof(filename_len)); totlen += filename_len + sizeof(size_t); if (hdr.len < totlen || filename_len == SIZE_T_MAX) error("corrupted message received"); if (filename_len > 0) { if ((filename = calloc(1, filename_len + 1)) == NULL) error("%m"); buf_read(fd, filename, filename_len); } else filename = NULL; buf_read(fd, &servername_len, sizeof(servername_len)); totlen += servername_len + sizeof(size_t); if (hdr.len < totlen || servername_len == SIZE_T_MAX) error("corrupted message received"); if (servername_len > 0) { if ((servername = calloc(1, servername_len + 1)) == NULL) error("%m"); buf_read(fd, servername, servername_len); } else servername = NULL; buf_read(fd, &prefix_len, sizeof(prefix_len)); totlen += prefix_len; if (hdr.len < totlen || prefix_len == SIZE_T_MAX) error("corrupted message received"); if (prefix_len > 0) { if ((prefix = calloc(1, prefix_len + 1)) == NULL) error("%m"); buf_read(fd, prefix, prefix_len); } else prefix = NULL; for (i = 0; i < 256; i++) { totlen += sizeof(optlen); if (hdr.len < totlen) error("corrupted message received"); buf_read(fd, &optlen, sizeof(optlen)); lease.options[i].data = NULL; lease.options[i].len = optlen; if (optlen > 0) { totlen += optlen; if (hdr.len < totlen || optlen == SIZE_T_MAX) error("corrupted message received"); lease.options[i].data = calloc(1, optlen + 1); if (lease.options[i].data == NULL) error("%m"); buf_read(fd, lease.options[i].data, optlen); } } lease.server_name = servername; lease.filename = filename; priv_script_write_params(prefix, &lease); free(servername); free(filename); free(prefix); for (i = 0; i < 256; i++) if (lease.options[i].len > 0) free(lease.options[i].data); break; case IMSG_SCRIPT_GO: if (hdr.len != sizeof(hdr)) error("corrupted message received"); ret = priv_script_go(); hdr.code = IMSG_SCRIPT_GO_RET; hdr.len = sizeof(struct imsg_hdr) + sizeof(int); if ((buf = buf_open(hdr.len)) == NULL) error("buf_open: %m"); if (buf_add(buf, &hdr, sizeof(hdr))) error("buf_add: %m"); if (buf_add(buf, &ret, sizeof(ret))) error("buf_add: %m"); if (buf_close(fd, buf) == -1) error("buf_close: %m"); break; case IMSG_SEND_PACKET: send_packet_priv(ifi, &hdr, fd); break; default: error("received unknown message, code %d", hdr.code); } }