1 /* $OpenBSD: imsg_util.c,v 1.1 2010/12/22 17:43:10 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 #include "ikev2.h" 43 44 void 45 imsg_event_add(struct imsgev *iev) 46 { 47 if (iev->handler == NULL) { 48 imsg_flush(&iev->ibuf); 49 return; 50 } 51 52 iev->events = EV_READ; 53 if (iev->ibuf.w.queued) 54 iev->events |= EV_WRITE; 55 56 event_del(&iev->ev); 57 event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev->data); 58 event_add(&iev->ev, NULL); 59 } 60 61 int 62 imsg_compose_event(struct imsgev *iev, u_int16_t type, u_int32_t peerid, 63 pid_t pid, int fd, void *data, u_int16_t datalen) 64 { 65 int ret; 66 67 if ((ret = imsg_compose(&iev->ibuf, type, peerid, 68 pid, fd, data, datalen)) == -1) 69 return (ret); 70 imsg_event_add(iev); 71 return (ret); 72 } 73 74 int 75 imsg_composev_event(struct imsgev *iev, u_int16_t type, u_int32_t peerid, 76 pid_t pid, int fd, const struct iovec *iov, int iovcnt) 77 { 78 int ret; 79 80 if ((ret = imsg_composev(&iev->ibuf, type, peerid, 81 pid, fd, iov, iovcnt)) == -1) 82 return (ret); 83 imsg_event_add(iev); 84 return (ret); 85 } 86 87 int 88 imsg_compose_proc(struct iked *env, enum iked_procid id, 89 u_int16_t type, int fd, void *data, u_int16_t datalen) 90 { 91 return (imsg_compose_event(&env->sc_ievs[id], 92 type, -1, 0, fd, data, datalen)); 93 } 94 95 int 96 imsg_composev_proc(struct iked *env, enum iked_procid id, 97 u_int16_t type, int fd, const struct iovec *iov, int iovcnt) 98 { 99 return (imsg_composev_event(&env->sc_ievs[id], 100 type, -1, 0, fd, iov, iovcnt)); 101 } 102 103 int 104 imsg_forward_proc(struct iked *env, struct imsg *imsg, 105 enum iked_procid id) 106 { 107 return (imsg_compose_proc(env, id, imsg->hdr.type, 108 imsg->fd, imsg->data, IMSG_DATA_SIZE(imsg))); 109 } 110 111 void 112 imsg_flush_proc(struct iked *env, enum iked_procid id) 113 { 114 imsg_flush(&env->sc_ievs[id].ibuf); 115 } 116 117 /* 118 * Extending the imsg buffer API for internal use 119 */ 120 121 int 122 ibuf_cat(struct ibuf *dst, struct ibuf *src) 123 { 124 return (ibuf_add(dst, src->buf, ibuf_size(src))); 125 } 126 127 void 128 ibuf_zero(struct ibuf *buf) 129 { 130 memset(buf->buf, 0, buf->wpos); 131 } 132 133 struct ibuf * 134 ibuf_new(void *data, size_t len) 135 { 136 struct ibuf *buf; 137 138 if ((buf = ibuf_dynamic(len, 139 IKED_MSGBUF_MAX)) == NULL) 140 return (NULL); 141 142 ibuf_zero(buf); 143 144 if (data == NULL && len) { 145 if (ibuf_advance(buf, len) == NULL) { 146 ibuf_free(buf); 147 return (NULL); 148 } 149 } else { 150 if (ibuf_add(buf, data, len) != 0) { 151 ibuf_free(buf); 152 return (NULL); 153 } 154 } 155 156 return (buf); 157 } 158 159 struct ibuf * 160 ibuf_static(void) 161 { 162 struct ibuf *buf; 163 164 if ((buf = ibuf_open(IKED_MSGBUF_MAX)) == NULL) 165 return (NULL); 166 167 ibuf_zero(buf); 168 169 return (buf); 170 } 171 172 void * 173 ibuf_advance(struct ibuf *buf, size_t len) 174 { 175 void *ptr; 176 177 if ((ptr = ibuf_reserve(buf, len)) != NULL) 178 memset(ptr, 0, len); 179 180 return (ptr); 181 } 182 183 void 184 ibuf_release(struct ibuf *buf) 185 { 186 if (buf == NULL) 187 return; 188 if (buf->buf != NULL) 189 free(buf->buf); 190 free(buf); 191 } 192 193 size_t 194 ibuf_length(struct ibuf *buf) 195 { 196 if (buf == NULL || buf->buf == NULL) 197 return (0); 198 return (ibuf_size(buf)); 199 } 200 201 u_int8_t * 202 ibuf_data(struct ibuf *buf) 203 { 204 return (ibuf_seek(buf, 0, 0)); 205 } 206 207 void * 208 ibuf_getdata(struct ibuf *buf, size_t len) 209 { 210 void *data; 211 212 if ((data = ibuf_seek(buf, buf->rpos, len)) == NULL) 213 return (NULL); 214 buf->rpos += len; 215 216 return (data); 217 } 218 219 struct ibuf * 220 ibuf_get(struct ibuf *buf, size_t len) 221 { 222 void *data; 223 224 if ((data = ibuf_getdata(buf, len)) == NULL) 225 return (NULL); 226 227 return (ibuf_new(data, len)); 228 } 229 230 struct ibuf * 231 ibuf_dup(struct ibuf *buf) 232 { 233 if (buf == NULL) 234 return (NULL); 235 return (ibuf_new(ibuf_data(buf), ibuf_size(buf))); 236 } 237 238 struct ibuf * 239 ibuf_random(size_t len) 240 { 241 struct ibuf *buf; 242 void *ptr; 243 244 if ((buf = ibuf_open(len)) == NULL) 245 return (NULL); 246 if ((ptr = ibuf_reserve(buf, len)) == NULL) { 247 ibuf_free(buf); 248 return (NULL); 249 } 250 arc4random_buf(ptr, len); 251 return (buf); 252 } 253 254 int 255 ibuf_setsize(struct ibuf *buf, size_t len) 256 { 257 if (len > buf->size) 258 return (-1); 259 buf->wpos = len; 260 return (0); 261 } 262 263 int 264 ibuf_prepend(struct ibuf *buf, void *data, size_t len) 265 { 266 struct ibuf *new; 267 268 /* Swap buffers (we could also use memmove here) */ 269 if ((new = ibuf_new(data, len)) == NULL) 270 return (-1); 271 if (ibuf_cat(new, buf) == -1) { 272 ibuf_release(new); 273 return (-1); 274 } 275 free(buf->buf); 276 memcpy(buf, new, sizeof(*buf)); 277 free(new); 278 279 return (0); 280 } 281