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