int control_compose(void *ch, u_int16_t type, void *buf, size_t len) { struct pdu *pdu; struct ctrlmsghdr *cmh; void *ptr; if (PDU_LEN(len) > CONTROL_READ_SIZE - PDU_LEN(sizeof(*cmh))) return -1; if ((pdu = pdu_new()) == NULL) return -1; if ((cmh = pdu_alloc(sizeof(*cmh))) == NULL) goto fail; bzero(cmh, sizeof(*cmh)); cmh->type = type; cmh->len[0] = len; pdu_addbuf(pdu, cmh, sizeof(*cmh), 0); if (len > 0) { if ((ptr = pdu_alloc(len)) == NULL) goto fail; bcopy(buf, ptr, len); pdu_addbuf(pdu, ptr, len, 1); } return control_queue(ch, pdu); fail: pdu_free(pdu); return -1; }
struct pdu * control_getpdu(char *buf, size_t len) { struct pdu *p; struct ctrlmsghdr *cmh; void *data; size_t n; int i; if (len < sizeof(*cmh)) return NULL; if (!(p = pdu_new())) return NULL; n = sizeof(*cmh); cmh = pdu_alloc(n); bcopy(buf, cmh, n); buf += n; len -= n; if (pdu_addbuf(p, cmh, n, 0)) { free(cmh); fail: pdu_free(p); return NULL; } for (i = 0; i < 3; i++) { n = cmh->len[i]; if (n == 0) continue; if (PDU_LEN(n) > len) goto fail; if (!(data = pdu_alloc(n))) goto fail; bcopy(buf, data, n); if (pdu_addbuf(p, data, n, i + 1)) { free(data); goto fail; } buf += PDU_LEN(n); len -= PDU_LEN(n); } return p; }
void * pdu_dup(void *data, size_t len) { void *p; if ((p = malloc(PDU_LEN(len)))) memcpy(p, data, len); return p; }
int control_build(void *ch, u_int16_t type, int argc, struct ctrldata *argv) { struct pdu *pdu; struct ctrlmsghdr *cmh; size_t size = 0; int i; if (argc > (int)nitems(cmh->len)) return -1; for (i = 0; i < argc; i++) size += argv[i].len; if (PDU_LEN(size) > CONTROL_READ_SIZE - PDU_LEN(sizeof(*cmh))) return -1; if ((pdu = pdu_new()) == NULL) return -1; if ((cmh = pdu_alloc(sizeof(*cmh))) == NULL) goto fail; bzero(cmh, sizeof(*cmh)); cmh->type = type; pdu_addbuf(pdu, cmh, sizeof(*cmh), 0); for (i = 0; i < argc; i++) if (argv[i].len > 0) { void *ptr; cmh->len[i] = argv[i].len; if ((ptr = pdu_alloc(argv[i].len)) == NULL) goto fail; memcpy(ptr, argv[i].buf, argv[i].len); pdu_addbuf(pdu, ptr, argv[i].len, i + 1); } control_queue(ch, pdu); return 0; fail: pdu_free(pdu); return -1; }
void * pdu_alloc(size_t len) { return malloc(PDU_LEN(len)); }