1 /* $OpenBSD: imsg_util.c,v 1.13 2021/05/17 08:14:37 tobhe Exp $ */ 2 3 /* 4 * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org> 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 #include <sys/queue.h> 20 #include <sys/socket.h> 21 #include <sys/uio.h> 22 23 #include <netdb.h> 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <unistd.h> 27 #include <string.h> 28 #include <errno.h> 29 #include <fcntl.h> 30 #include <ctype.h> 31 #include <event.h> 32 33 #include "iked.h" 34 35 /* 36 * Extending the imsg buffer API for internal use 37 */ 38 39 int 40 ibuf_cat(struct ibuf *dst, struct ibuf *src) 41 { 42 return (ibuf_add(dst, src->buf, ibuf_size(src))); 43 } 44 45 void 46 ibuf_zero(struct ibuf *buf) 47 { 48 explicit_bzero(buf->buf, buf->wpos); 49 } 50 51 struct ibuf * 52 ibuf_new(const void *data, size_t len) 53 { 54 struct ibuf *buf; 55 56 if ((buf = ibuf_dynamic(len, 57 IKED_MSGBUF_MAX)) == NULL) 58 return (NULL); 59 60 ibuf_zero(buf); 61 62 if (len == 0) 63 return (buf); 64 65 if (data == NULL) { 66 if (ibuf_advance(buf, len) == NULL) { 67 ibuf_free(buf); 68 return (NULL); 69 } 70 } else { 71 if (ibuf_add(buf, data, len) != 0) { 72 ibuf_free(buf); 73 return (NULL); 74 } 75 } 76 77 return (buf); 78 } 79 80 struct ibuf * 81 ibuf_static(void) 82 { 83 struct ibuf *buf; 84 85 if ((buf = ibuf_open(IKED_MSGBUF_MAX)) == NULL) 86 return (NULL); 87 88 ibuf_zero(buf); 89 90 return (buf); 91 } 92 93 void * 94 ibuf_advance(struct ibuf *buf, size_t len) 95 { 96 void *ptr; 97 98 if ((ptr = ibuf_reserve(buf, len)) != NULL) 99 memset(ptr, 0, len); 100 101 return (ptr); 102 } 103 104 void 105 ibuf_release(struct ibuf *buf) 106 { 107 if (buf == NULL) 108 return; 109 if (buf->buf != NULL) { 110 ibuf_zero(buf); 111 free(buf->buf); 112 } 113 free(buf); 114 } 115 116 size_t 117 ibuf_length(struct ibuf *buf) 118 { 119 if (buf == NULL || buf->buf == NULL) 120 return (0); 121 return (ibuf_size(buf)); 122 } 123 124 uint8_t * 125 ibuf_data(struct ibuf *buf) 126 { 127 return (ibuf_seek(buf, 0, 0)); 128 } 129 130 void * 131 ibuf_getdata(struct ibuf *buf, size_t len) 132 { 133 void *data; 134 135 if ((data = ibuf_seek(buf, buf->rpos, len)) == NULL) 136 return (NULL); 137 buf->rpos += len; 138 139 return (data); 140 } 141 142 struct ibuf * 143 ibuf_get(struct ibuf *buf, size_t len) 144 { 145 void *data; 146 147 if ((data = ibuf_getdata(buf, len)) == NULL) 148 return (NULL); 149 150 return (ibuf_new(data, len)); 151 } 152 153 struct ibuf * 154 ibuf_dup(struct ibuf *buf) 155 { 156 if (buf == NULL) 157 return (NULL); 158 return (ibuf_new(ibuf_data(buf), ibuf_size(buf))); 159 } 160 161 struct ibuf * 162 ibuf_random(size_t len) 163 { 164 struct ibuf *buf; 165 void *ptr; 166 167 if ((buf = ibuf_open(len)) == NULL) 168 return (NULL); 169 if ((ptr = ibuf_reserve(buf, len)) == NULL) { 170 ibuf_free(buf); 171 return (NULL); 172 } 173 arc4random_buf(ptr, len); 174 return (buf); 175 } 176 177 int 178 ibuf_setsize(struct ibuf *buf, size_t len) 179 { 180 if (len > buf->size) 181 return (-1); 182 buf->wpos = len; 183 return (0); 184 } 185 186 int 187 ibuf_prepend(struct ibuf *buf, void *data, size_t len) 188 { 189 struct ibuf *new; 190 191 /* Swap buffers (we could also use memmove here) */ 192 if ((new = ibuf_new(data, len)) == NULL) 193 return (-1); 194 if (ibuf_cat(new, buf) == -1) { 195 ibuf_release(new); 196 return (-1); 197 } 198 free(buf->buf); 199 memcpy(buf, new, sizeof(*buf)); 200 free(new); 201 202 return (0); 203 } 204 205 int 206 ibuf_strcat(struct ibuf **buf, const char *s) 207 { 208 size_t slen; 209 210 if (buf == NULL) 211 return (-1); 212 slen = strlen(s); 213 if (*buf == NULL) { 214 if ((*buf = ibuf_new(s, slen)) == NULL) 215 return (-1); 216 return (0); 217 } 218 return (ibuf_add(*buf, s, slen)); 219 } 220 221 int 222 ibuf_strlen(struct ibuf *buf) 223 { 224 if (ibuf_length(buf) > INT_MAX) 225 return (INT_MAX); 226 return ((int)ibuf_length(buf)); 227 } 228