xref: /openbsd/sbin/iked/imsg_util.c (revision 274d7c50)
1 /*	$OpenBSD: imsg_util.c,v 1.11 2017/01/20 14:10:05 mikeb 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 (data == NULL && len) {
63 		if (ibuf_advance(buf, len) == NULL) {
64 			ibuf_free(buf);
65 			return (NULL);
66 		}
67 	} else {
68 		if (ibuf_add(buf, data, len) != 0) {
69 			ibuf_free(buf);
70 			return (NULL);
71 		}
72 	}
73 
74 	return (buf);
75 }
76 
77 struct ibuf *
78 ibuf_static(void)
79 {
80 	struct ibuf	*buf;
81 
82 	if ((buf = ibuf_open(IKED_MSGBUF_MAX)) == NULL)
83 		return (NULL);
84 
85 	ibuf_zero(buf);
86 
87 	return (buf);
88 }
89 
90 void *
91 ibuf_advance(struct ibuf *buf, size_t len)
92 {
93 	void	*ptr;
94 
95 	if ((ptr = ibuf_reserve(buf, len)) != NULL)
96 		memset(ptr, 0, len);
97 
98 	return (ptr);
99 }
100 
101 void
102 ibuf_release(struct ibuf *buf)
103 {
104 	if (buf == NULL)
105 		return;
106 	if (buf->buf != NULL) {
107 		ibuf_zero(buf);
108 		free(buf->buf);
109 	}
110 	free(buf);
111 }
112 
113 size_t
114 ibuf_length(struct ibuf *buf)
115 {
116 	if (buf == NULL || buf->buf == NULL)
117 		return (0);
118 	return (ibuf_size(buf));
119 }
120 
121 uint8_t *
122 ibuf_data(struct ibuf *buf)
123 {
124 	return (ibuf_seek(buf, 0, 0));
125 }
126 
127 void *
128 ibuf_getdata(struct ibuf *buf, size_t len)
129 {
130 	void	*data;
131 
132 	if ((data = ibuf_seek(buf, buf->rpos, len)) == NULL)
133 		return (NULL);
134 	buf->rpos += len;
135 
136 	return (data);
137 }
138 
139 struct ibuf *
140 ibuf_get(struct ibuf *buf, size_t len)
141 {
142 	void		*data;
143 
144 	if ((data = ibuf_getdata(buf, len)) == NULL)
145 		return (NULL);
146 
147 	return (ibuf_new(data, len));
148 }
149 
150 struct ibuf *
151 ibuf_dup(struct ibuf *buf)
152 {
153 	if (buf == NULL)
154 		return (NULL);
155 	return (ibuf_new(ibuf_data(buf), ibuf_size(buf)));
156 }
157 
158 struct ibuf *
159 ibuf_random(size_t len)
160 {
161 	struct ibuf	*buf;
162 	void		*ptr;
163 
164 	if ((buf = ibuf_open(len)) == NULL)
165 		return (NULL);
166 	if ((ptr = ibuf_reserve(buf, len)) == NULL) {
167 		ibuf_free(buf);
168 		return (NULL);
169 	}
170 	arc4random_buf(ptr, len);
171 	return (buf);
172 }
173 
174 int
175 ibuf_setsize(struct ibuf *buf, size_t len)
176 {
177 	if (len > buf->size)
178 		return (-1);
179 	buf->wpos = len;
180 	return (0);
181 }
182 
183 int
184 ibuf_prepend(struct ibuf *buf, void *data, size_t len)
185 {
186 	struct ibuf	*new;
187 
188 	/* Swap buffers (we could also use memmove here) */
189 	if ((new = ibuf_new(data, len)) == NULL)
190 		return (-1);
191 	if (ibuf_cat(new, buf) == -1) {
192 		ibuf_release(new);
193 		return (-1);
194 	}
195 	free(buf->buf);
196 	memcpy(buf, new, sizeof(*buf));
197 	free(new);
198 
199 	return (0);
200 }
201