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