xref: /openbsd/sbin/iked/imsg_util.c (revision 3d8817e4)
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