diff options
Diffstat (limited to 'usr.sbin/switchd/imsg_util.c')
| -rw-r--r-- | usr.sbin/switchd/imsg_util.c | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/usr.sbin/switchd/imsg_util.c b/usr.sbin/switchd/imsg_util.c new file mode 100644 index 00000000000..9274276f62e --- /dev/null +++ b/usr.sbin/switchd/imsg_util.c @@ -0,0 +1,226 @@ +/* $OpenBSD: imsg_util.c,v 1.1 2016/07/19 16:54:26 reyk Exp $ */ + +/* + * Copyright (c) 2010-2016 Reyk Floeter <reyk@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/queue.h> +#include <sys/socket.h> +#include <sys/uio.h> + +#include <net/if.h> +#include <netinet/in_systm.h> +#include <netinet/in.h> +#include <netinet/ip.h> +#include <netinet/tcp.h> +#include <arpa/inet.h> +#include <netdb.h> + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> +#include <ctype.h> +#include <event.h> +#include <imsg.h> + +#include "switchd.h" + +/* + * Extending the imsg buffer API for internal use + */ + +int +ibuf_cat(struct ibuf *dst, struct ibuf *src) +{ + return (ibuf_add(dst, src->buf, ibuf_size(src))); +} + +void +ibuf_zero(struct ibuf *buf) +{ + memset(buf->buf, 0, buf->wpos); +} + +void +ibuf_reset(struct ibuf *buf) +{ + ibuf_zero(buf); + buf->rpos = buf->wpos = 0; +} + +struct ibuf * +ibuf_new(void *data, size_t len) +{ + struct ibuf *buf; + + if ((buf = ibuf_dynamic(len, + SWITCHD_MSGBUF_MAX)) == NULL) + return (NULL); + + ibuf_zero(buf); + + if (data == NULL && len) { + if (ibuf_advance(buf, len) == NULL) { + ibuf_free(buf); + return (NULL); + } + } else { + if (ibuf_add(buf, data, len) != 0) { + ibuf_free(buf); + return (NULL); + } + } + + return (buf); +} + +struct ibuf * +ibuf_static(void) +{ + struct ibuf *buf; + + if ((buf = ibuf_open(SWITCHD_MSGBUF_MAX)) == NULL) + return (NULL); + + ibuf_zero(buf); + + return (buf); +} + +void * +ibuf_advance(struct ibuf *buf, size_t len) +{ + void *ptr; + + if ((ptr = ibuf_reserve(buf, len)) != NULL) + memset(ptr, 0, len); + + return (ptr); +} + +void +ibuf_release(struct ibuf *buf) +{ + if (buf == NULL) + return; + if (buf->buf != NULL) + free(buf->buf); + free(buf); +} + +size_t +ibuf_length(struct ibuf *buf) +{ + if (buf == NULL || buf->buf == NULL) + return (0); + return (ibuf_size(buf)); +} + +uint8_t * +ibuf_data(struct ibuf *buf) +{ + return (ibuf_seek(buf, 0, 0)); +} + +void * +ibuf_getdata(struct ibuf *buf, size_t len) +{ + void *data; + + if ((data = ibuf_seek(buf, buf->rpos, len)) == NULL) + return (NULL); + buf->rpos += len; + + return (data); +} + +ssize_t +ibuf_dataleft(struct ibuf *buf) +{ + return (buf->wpos - buf->rpos); +} + +size_t +ibuf_dataoffset(struct ibuf *buf) +{ + return (buf->rpos); +} + +struct ibuf * +ibuf_get(struct ibuf *buf, size_t len) +{ + void *data; + + if ((data = ibuf_getdata(buf, len)) == NULL) + return (NULL); + + return (ibuf_new(data, len)); +} + +struct ibuf * +ibuf_dup(struct ibuf *buf) +{ + if (buf == NULL) + return (NULL); + return (ibuf_new(ibuf_data(buf), ibuf_size(buf))); +} + +struct ibuf * +ibuf_random(size_t len) +{ + struct ibuf *buf; + void *ptr; + + if ((buf = ibuf_open(len)) == NULL) + return (NULL); + if ((ptr = ibuf_reserve(buf, len)) == NULL) { + ibuf_free(buf); + return (NULL); + } + arc4random_buf(ptr, len); + return (buf); +} + +int +ibuf_setsize(struct ibuf *buf, size_t len) +{ + if (len > buf->size) + return (-1); + buf->wpos = len; + return (0); +} + +int +ibuf_prepend(struct ibuf *buf, void *data, size_t len) +{ + struct ibuf *new; + + /* Swap buffers (we could also use memmove here) */ + if ((new = ibuf_new(data, len)) == NULL) + return (-1); + if (ibuf_cat(new, buf) == -1) { + ibuf_release(new); + return (-1); + } + free(buf->buf); + memcpy(buf, new, sizeof(*buf)); + free(new); + + return (0); +} |
