xref: /freebsd-src/contrib/libevent/event_tagging.c (revision b50261e21f39a6c7249a49e7b60aa878c98512a8)
1c43e99fdSEd Maste /*
2c43e99fdSEd Maste  * Copyright (c) 2003-2009 Niels Provos <provos@citi.umich.edu>
3c43e99fdSEd Maste  * Copyright (c) 2009-2012 Niels Provos and Nick Mathewson
4c43e99fdSEd Maste  *
5c43e99fdSEd Maste  * Redistribution and use in source and binary forms, with or without
6c43e99fdSEd Maste  * modification, are permitted provided that the following conditions
7c43e99fdSEd Maste  * are met:
8c43e99fdSEd Maste  * 1. Redistributions of source code must retain the above copyright
9c43e99fdSEd Maste  *    notice, this list of conditions and the following disclaimer.
10c43e99fdSEd Maste  * 2. Redistributions in binary form must reproduce the above copyright
11c43e99fdSEd Maste  *    notice, this list of conditions and the following disclaimer in the
12c43e99fdSEd Maste  *    documentation and/or other materials provided with the distribution.
13c43e99fdSEd Maste  * 3. The name of the author may not be used to endorse or promote products
14c43e99fdSEd Maste  *    derived from this software without specific prior written permission.
15c43e99fdSEd Maste  *
16c43e99fdSEd Maste  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17c43e99fdSEd Maste  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18c43e99fdSEd Maste  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19c43e99fdSEd Maste  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20c43e99fdSEd Maste  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21c43e99fdSEd Maste  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22c43e99fdSEd Maste  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23c43e99fdSEd Maste  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24c43e99fdSEd Maste  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25c43e99fdSEd Maste  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26c43e99fdSEd Maste  */
27c43e99fdSEd Maste 
28c43e99fdSEd Maste #include "event2/event-config.h"
29c43e99fdSEd Maste #include "evconfig-private.h"
30c43e99fdSEd Maste 
31c43e99fdSEd Maste #ifdef EVENT__HAVE_SYS_TYPES_H
32c43e99fdSEd Maste #include <sys/types.h>
33c43e99fdSEd Maste #endif
34c43e99fdSEd Maste #ifdef EVENT__HAVE_SYS_PARAM_H
35c43e99fdSEd Maste #include <sys/param.h>
36c43e99fdSEd Maste #endif
37c43e99fdSEd Maste 
38c43e99fdSEd Maste #ifdef _WIN32
39c43e99fdSEd Maste #define WIN32_LEAN_AND_MEAN
40c43e99fdSEd Maste #include <winsock2.h>
41c43e99fdSEd Maste #include <windows.h>
42c43e99fdSEd Maste #undef WIN32_LEAN_AND_MEAN
43c43e99fdSEd Maste #endif
44c43e99fdSEd Maste 
45c43e99fdSEd Maste #ifdef EVENT__HAVE_SYS_IOCTL_H
46c43e99fdSEd Maste #include <sys/ioctl.h>
47c43e99fdSEd Maste #endif
48c43e99fdSEd Maste #include <sys/queue.h>
49c43e99fdSEd Maste #ifdef EVENT__HAVE_SYS_TIME_H
50c43e99fdSEd Maste #include <sys/time.h>
51c43e99fdSEd Maste #endif
52c43e99fdSEd Maste 
53c43e99fdSEd Maste #include <errno.h>
54c43e99fdSEd Maste #include <stdio.h>
55c43e99fdSEd Maste #include <stdlib.h>
56c43e99fdSEd Maste #include <string.h>
57c43e99fdSEd Maste #ifndef _WIN32
58c43e99fdSEd Maste #include <syslog.h>
59c43e99fdSEd Maste #endif
60c43e99fdSEd Maste #ifdef EVENT__HAVE_UNISTD_H
61c43e99fdSEd Maste #include <unistd.h>
62c43e99fdSEd Maste #endif
63c43e99fdSEd Maste #include <limits.h>
64c43e99fdSEd Maste 
65c43e99fdSEd Maste #include "event2/event.h"
66c43e99fdSEd Maste #include "event2/tag.h"
67c43e99fdSEd Maste #include "event2/buffer.h"
68c43e99fdSEd Maste #include "log-internal.h"
69c43e99fdSEd Maste #include "mm-internal.h"
70c43e99fdSEd Maste #include "util-internal.h"
71c43e99fdSEd Maste 
72c43e99fdSEd Maste /*
73c43e99fdSEd Maste   Here's our wire format:
74c43e99fdSEd Maste 
75c43e99fdSEd Maste   Stream = TaggedData*
76c43e99fdSEd Maste 
77c43e99fdSEd Maste   TaggedData = Tag Length Data
78c43e99fdSEd Maste        where the integer value of 'Length' is the length of 'data'.
79c43e99fdSEd Maste 
80c43e99fdSEd Maste   Tag = HByte* LByte
81c43e99fdSEd Maste        where HByte is a byte with the high bit set, and LByte is a byte
82c43e99fdSEd Maste        with the high bit clear. The integer value of the tag is taken
83c43e99fdSEd Maste        by concatenating the lower 7 bits from all the tags.  So for example,
84c43e99fdSEd Maste        the tag 0x66 is encoded as [66], whereas the tag 0x166 is encoded as
85c43e99fdSEd Maste        [82 66]
86c43e99fdSEd Maste 
87c43e99fdSEd Maste   Length = Integer
88c43e99fdSEd Maste 
89c43e99fdSEd Maste   Integer = NNibbles Nibble* Padding?
90c43e99fdSEd Maste        where NNibbles is a 4-bit value encoding the number of nibbles-1,
91c43e99fdSEd Maste        and each Nibble is 4 bits worth of encoded integer, in big-endian
92c43e99fdSEd Maste        order.  If the total encoded integer size is an odd number of nibbles,
93c43e99fdSEd Maste        a final padding nibble with value 0 is appended.
94c43e99fdSEd Maste */
95c43e99fdSEd Maste 
96*b50261e2SCy Schubert EVENT2_EXPORT_SYMBOL
97c43e99fdSEd Maste int evtag_decode_int(ev_uint32_t *pnumber, struct evbuffer *evbuf);
98*b50261e2SCy Schubert EVENT2_EXPORT_SYMBOL
99c43e99fdSEd Maste int evtag_decode_int64(ev_uint64_t *pnumber, struct evbuffer *evbuf);
100*b50261e2SCy Schubert EVENT2_EXPORT_SYMBOL
101c43e99fdSEd Maste int evtag_encode_tag(struct evbuffer *evbuf, ev_uint32_t tag);
102*b50261e2SCy Schubert EVENT2_EXPORT_SYMBOL
103c43e99fdSEd Maste int evtag_decode_tag(ev_uint32_t *ptag, struct evbuffer *evbuf);
104c43e99fdSEd Maste 
105c43e99fdSEd Maste void
evtag_init(void)106c43e99fdSEd Maste evtag_init(void)
107c43e99fdSEd Maste {
108c43e99fdSEd Maste }
109c43e99fdSEd Maste 
110c43e99fdSEd Maste /*
111c43e99fdSEd Maste  * We encode integers by nibbles; the first nibble contains the number
112c43e99fdSEd Maste  * of significant nibbles - 1;  this allows us to encode up to 64-bit
113c43e99fdSEd Maste  * integers.  This function is byte-order independent.
114c43e99fdSEd Maste  *
115c43e99fdSEd Maste  * @param number a 32-bit unsigned integer to encode
116c43e99fdSEd Maste  * @param data a pointer to where the data should be written.  Must
117c43e99fdSEd Maste  *    have at least 5 bytes free.
118c43e99fdSEd Maste  * @return the number of bytes written into data.
119c43e99fdSEd Maste  */
120c43e99fdSEd Maste 
121c43e99fdSEd Maste #define ENCODE_INT_INTERNAL(data, number) do {				\
122c43e99fdSEd Maste 	int off = 1, nibbles = 0;					\
123c43e99fdSEd Maste 									\
124c43e99fdSEd Maste 	memset(data, 0, sizeof(number)+1);				\
125c43e99fdSEd Maste 	while (number) {						\
126c43e99fdSEd Maste 		if (off & 0x1)						\
127c43e99fdSEd Maste 			data[off/2] = (data[off/2] & 0xf0) | (number & 0x0f); \
128c43e99fdSEd Maste 		else							\
129c43e99fdSEd Maste 			data[off/2] = (data[off/2] & 0x0f) |		\
130c43e99fdSEd Maste 			    ((number & 0x0f) << 4);			\
131c43e99fdSEd Maste 		number >>= 4;						\
132c43e99fdSEd Maste 		off++;							\
133c43e99fdSEd Maste 	}								\
134c43e99fdSEd Maste 									\
135c43e99fdSEd Maste 	if (off > 2)							\
136c43e99fdSEd Maste 		nibbles = off - 2;					\
137c43e99fdSEd Maste 									\
138c43e99fdSEd Maste 	/* Off - 1 is the number of encoded nibbles */			\
139c43e99fdSEd Maste 	data[0] = (data[0] & 0x0f) | ((nibbles & 0x0f) << 4);		\
140c43e99fdSEd Maste 									\
141c43e99fdSEd Maste 	return ((off + 1) / 2);						\
142c43e99fdSEd Maste } while (0)
143c43e99fdSEd Maste 
144c43e99fdSEd Maste static inline int
encode_int_internal(ev_uint8_t * data,ev_uint32_t number)145c43e99fdSEd Maste encode_int_internal(ev_uint8_t *data, ev_uint32_t number)
146c43e99fdSEd Maste {
147c43e99fdSEd Maste 	ENCODE_INT_INTERNAL(data, number);
148c43e99fdSEd Maste }
149c43e99fdSEd Maste 
150c43e99fdSEd Maste static inline int
encode_int64_internal(ev_uint8_t * data,ev_uint64_t number)151c43e99fdSEd Maste encode_int64_internal(ev_uint8_t *data, ev_uint64_t number)
152c43e99fdSEd Maste {
153c43e99fdSEd Maste 	ENCODE_INT_INTERNAL(data, number);
154c43e99fdSEd Maste }
155c43e99fdSEd Maste 
156c43e99fdSEd Maste void
evtag_encode_int(struct evbuffer * evbuf,ev_uint32_t number)157c43e99fdSEd Maste evtag_encode_int(struct evbuffer *evbuf, ev_uint32_t number)
158c43e99fdSEd Maste {
159c43e99fdSEd Maste 	ev_uint8_t data[5];
160c43e99fdSEd Maste 	int len = encode_int_internal(data, number);
161c43e99fdSEd Maste 	evbuffer_add(evbuf, data, len);
162c43e99fdSEd Maste }
163c43e99fdSEd Maste 
164c43e99fdSEd Maste void
evtag_encode_int64(struct evbuffer * evbuf,ev_uint64_t number)165c43e99fdSEd Maste evtag_encode_int64(struct evbuffer *evbuf, ev_uint64_t number)
166c43e99fdSEd Maste {
167c43e99fdSEd Maste 	ev_uint8_t data[9];
168c43e99fdSEd Maste 	int len = encode_int64_internal(data, number);
169c43e99fdSEd Maste 	evbuffer_add(evbuf, data, len);
170c43e99fdSEd Maste }
171c43e99fdSEd Maste 
172c43e99fdSEd Maste /*
173c43e99fdSEd Maste  * Support variable length encoding of tags; we use the high bit in each
174c43e99fdSEd Maste  * octet as a continuation signal.
175c43e99fdSEd Maste  */
176c43e99fdSEd Maste 
177c43e99fdSEd Maste int
evtag_encode_tag(struct evbuffer * evbuf,ev_uint32_t tag)178c43e99fdSEd Maste evtag_encode_tag(struct evbuffer *evbuf, ev_uint32_t tag)
179c43e99fdSEd Maste {
180c43e99fdSEd Maste 	int bytes = 0;
181c43e99fdSEd Maste 	ev_uint8_t data[5];
182c43e99fdSEd Maste 
183c43e99fdSEd Maste 	memset(data, 0, sizeof(data));
184c43e99fdSEd Maste 	do {
185c43e99fdSEd Maste 		ev_uint8_t lower = tag & 0x7f;
186c43e99fdSEd Maste 		tag >>= 7;
187c43e99fdSEd Maste 
188c43e99fdSEd Maste 		if (tag)
189c43e99fdSEd Maste 			lower |= 0x80;
190c43e99fdSEd Maste 
191c43e99fdSEd Maste 		data[bytes++] = lower;
192c43e99fdSEd Maste 	} while (tag);
193c43e99fdSEd Maste 
194c43e99fdSEd Maste 	if (evbuf != NULL)
195c43e99fdSEd Maste 		evbuffer_add(evbuf, data, bytes);
196c43e99fdSEd Maste 
197c43e99fdSEd Maste 	return (bytes);
198c43e99fdSEd Maste }
199c43e99fdSEd Maste 
200c43e99fdSEd Maste static int
decode_tag_internal(ev_uint32_t * ptag,struct evbuffer * evbuf,int dodrain)201c43e99fdSEd Maste decode_tag_internal(ev_uint32_t *ptag, struct evbuffer *evbuf, int dodrain)
202c43e99fdSEd Maste {
203c43e99fdSEd Maste 	ev_uint32_t number = 0;
204c43e99fdSEd Maste 	size_t len = evbuffer_get_length(evbuf);
205c43e99fdSEd Maste 	ev_uint8_t *data;
206c43e99fdSEd Maste 	size_t count = 0;
207c43e99fdSEd Maste 	int  shift = 0, done = 0;
208c43e99fdSEd Maste 
209c43e99fdSEd Maste 	/*
210c43e99fdSEd Maste 	 * the encoding of a number is at most one byte more than its
211c43e99fdSEd Maste 	 * storage size.  however, it may also be much smaller.
212c43e99fdSEd Maste 	 */
213c43e99fdSEd Maste 	data = evbuffer_pullup(
214c43e99fdSEd Maste 		evbuf, len < sizeof(number) + 1 ? len : sizeof(number) + 1);
215c43e99fdSEd Maste 	if (!data)
216c43e99fdSEd Maste 		return (-1);
217c43e99fdSEd Maste 
218c43e99fdSEd Maste 	while (count++ < len) {
219c43e99fdSEd Maste 		ev_uint8_t lower = *data++;
220c43e99fdSEd Maste 		if (shift >= 28) {
221c43e99fdSEd Maste 			/* Make sure it fits into 32 bits */
222c43e99fdSEd Maste 			if (shift > 28)
223c43e99fdSEd Maste 				return (-1);
224c43e99fdSEd Maste 			if ((lower & 0x7f) > 15)
225c43e99fdSEd Maste 				return (-1);
226c43e99fdSEd Maste 		}
227c43e99fdSEd Maste 		number |= (lower & (unsigned)0x7f) << shift;
228c43e99fdSEd Maste 		shift += 7;
229c43e99fdSEd Maste 
230c43e99fdSEd Maste 		if (!(lower & 0x80)) {
231c43e99fdSEd Maste 			done = 1;
232c43e99fdSEd Maste 			break;
233c43e99fdSEd Maste 		}
234c43e99fdSEd Maste 	}
235c43e99fdSEd Maste 
236c43e99fdSEd Maste 	if (!done)
237c43e99fdSEd Maste 		return (-1);
238c43e99fdSEd Maste 
239c43e99fdSEd Maste 	if (dodrain)
240c43e99fdSEd Maste 		evbuffer_drain(evbuf, count);
241c43e99fdSEd Maste 
242c43e99fdSEd Maste 	if (ptag != NULL)
243c43e99fdSEd Maste 		*ptag = number;
244c43e99fdSEd Maste 
245c43e99fdSEd Maste 	return count > INT_MAX ? INT_MAX : (int)(count);
246c43e99fdSEd Maste }
247c43e99fdSEd Maste 
248c43e99fdSEd Maste int
evtag_decode_tag(ev_uint32_t * ptag,struct evbuffer * evbuf)249c43e99fdSEd Maste evtag_decode_tag(ev_uint32_t *ptag, struct evbuffer *evbuf)
250c43e99fdSEd Maste {
251c43e99fdSEd Maste 	return (decode_tag_internal(ptag, evbuf, 1 /* dodrain */));
252c43e99fdSEd Maste }
253c43e99fdSEd Maste 
254c43e99fdSEd Maste /*
255c43e99fdSEd Maste  * Marshal a data type, the general format is as follows:
256c43e99fdSEd Maste  *
257c43e99fdSEd Maste  * tag number: one byte; length: var bytes; payload: var bytes
258c43e99fdSEd Maste  */
259c43e99fdSEd Maste 
260c43e99fdSEd Maste void
evtag_marshal(struct evbuffer * evbuf,ev_uint32_t tag,const void * data,ev_uint32_t len)261c43e99fdSEd Maste evtag_marshal(struct evbuffer *evbuf, ev_uint32_t tag,
262c43e99fdSEd Maste     const void *data, ev_uint32_t len)
263c43e99fdSEd Maste {
264c43e99fdSEd Maste 	evtag_encode_tag(evbuf, tag);
265c43e99fdSEd Maste 	evtag_encode_int(evbuf, len);
266c43e99fdSEd Maste 	evbuffer_add(evbuf, (void *)data, len);
267c43e99fdSEd Maste }
268c43e99fdSEd Maste 
269c43e99fdSEd Maste void
evtag_marshal_buffer(struct evbuffer * evbuf,ev_uint32_t tag,struct evbuffer * data)270c43e99fdSEd Maste evtag_marshal_buffer(struct evbuffer *evbuf, ev_uint32_t tag,
271c43e99fdSEd Maste     struct evbuffer *data)
272c43e99fdSEd Maste {
273c43e99fdSEd Maste 	evtag_encode_tag(evbuf, tag);
274c43e99fdSEd Maste 	/* XXX support more than UINT32_MAX data */
275c43e99fdSEd Maste 	evtag_encode_int(evbuf, (ev_uint32_t)evbuffer_get_length(data));
276c43e99fdSEd Maste 	evbuffer_add_buffer(evbuf, data);
277c43e99fdSEd Maste }
278c43e99fdSEd Maste 
279c43e99fdSEd Maste /* Marshaling for integers */
280c43e99fdSEd Maste void
evtag_marshal_int(struct evbuffer * evbuf,ev_uint32_t tag,ev_uint32_t integer)281c43e99fdSEd Maste evtag_marshal_int(struct evbuffer *evbuf, ev_uint32_t tag, ev_uint32_t integer)
282c43e99fdSEd Maste {
283c43e99fdSEd Maste 	ev_uint8_t data[5];
284c43e99fdSEd Maste 	int len = encode_int_internal(data, integer);
285c43e99fdSEd Maste 
286c43e99fdSEd Maste 	evtag_encode_tag(evbuf, tag);
287c43e99fdSEd Maste 	evtag_encode_int(evbuf, len);
288c43e99fdSEd Maste 	evbuffer_add(evbuf, data, len);
289c43e99fdSEd Maste }
290c43e99fdSEd Maste 
291c43e99fdSEd Maste void
evtag_marshal_int64(struct evbuffer * evbuf,ev_uint32_t tag,ev_uint64_t integer)292c43e99fdSEd Maste evtag_marshal_int64(struct evbuffer *evbuf, ev_uint32_t tag,
293c43e99fdSEd Maste     ev_uint64_t integer)
294c43e99fdSEd Maste {
295c43e99fdSEd Maste 	ev_uint8_t data[9];
296c43e99fdSEd Maste 	int len = encode_int64_internal(data, integer);
297c43e99fdSEd Maste 
298c43e99fdSEd Maste 	evtag_encode_tag(evbuf, tag);
299c43e99fdSEd Maste 	evtag_encode_int(evbuf, len);
300c43e99fdSEd Maste 	evbuffer_add(evbuf, data, len);
301c43e99fdSEd Maste }
302c43e99fdSEd Maste 
303c43e99fdSEd Maste void
evtag_marshal_string(struct evbuffer * buf,ev_uint32_t tag,const char * string)304c43e99fdSEd Maste evtag_marshal_string(struct evbuffer *buf, ev_uint32_t tag, const char *string)
305c43e99fdSEd Maste {
306c43e99fdSEd Maste 	/* TODO support strings longer than UINT32_MAX ? */
307c43e99fdSEd Maste 	evtag_marshal(buf, tag, string, (ev_uint32_t)strlen(string));
308c43e99fdSEd Maste }
309c43e99fdSEd Maste 
310c43e99fdSEd Maste void
evtag_marshal_timeval(struct evbuffer * evbuf,ev_uint32_t tag,struct timeval * tv)311c43e99fdSEd Maste evtag_marshal_timeval(struct evbuffer *evbuf, ev_uint32_t tag, struct timeval *tv)
312c43e99fdSEd Maste {
313c43e99fdSEd Maste 	ev_uint8_t data[10];
314c43e99fdSEd Maste 	int len = encode_int_internal(data, tv->tv_sec);
315c43e99fdSEd Maste 	len += encode_int_internal(data + len, tv->tv_usec);
316c43e99fdSEd Maste 	evtag_marshal(evbuf, tag, data, len);
317c43e99fdSEd Maste }
318c43e99fdSEd Maste 
319c43e99fdSEd Maste #define DECODE_INT_INTERNAL(number, maxnibbles, pnumber, evbuf, offset) \
320c43e99fdSEd Maste do {									\
321c43e99fdSEd Maste 	ev_uint8_t *data;						\
322c43e99fdSEd Maste 	ev_ssize_t len = evbuffer_get_length(evbuf) - offset;		\
323c43e99fdSEd Maste 	int nibbles = 0;						\
324c43e99fdSEd Maste 									\
325c43e99fdSEd Maste 	if (len <= 0)							\
326c43e99fdSEd Maste 		return (-1);						\
327c43e99fdSEd Maste 									\
328c43e99fdSEd Maste 	/* XXX(niels): faster? */					\
329c43e99fdSEd Maste 	data = evbuffer_pullup(evbuf, offset + 1) + offset;		\
330c43e99fdSEd Maste 	if (!data)							\
331c43e99fdSEd Maste 		return (-1);						\
332c43e99fdSEd Maste 									\
333c43e99fdSEd Maste 	nibbles = ((data[0] & 0xf0) >> 4) + 1;				\
334c43e99fdSEd Maste 	if (nibbles > maxnibbles || (nibbles >> 1) + 1 > len)		\
335c43e99fdSEd Maste 		return (-1);						\
336c43e99fdSEd Maste 	len = (nibbles >> 1) + 1;					\
337c43e99fdSEd Maste 									\
338c43e99fdSEd Maste 	data = evbuffer_pullup(evbuf, offset + len) + offset;		\
339c43e99fdSEd Maste 	if (!data)							\
340c43e99fdSEd Maste 		return (-1);						\
341c43e99fdSEd Maste 									\
342c43e99fdSEd Maste 	while (nibbles > 0) {						\
343c43e99fdSEd Maste 		number <<= 4;						\
344c43e99fdSEd Maste 		if (nibbles & 0x1)					\
345c43e99fdSEd Maste 			number |= data[nibbles >> 1] & 0x0f;		\
346c43e99fdSEd Maste 		else							\
347c43e99fdSEd Maste 			number |= (data[nibbles >> 1] & 0xf0) >> 4;	\
348c43e99fdSEd Maste 		nibbles--;						\
349c43e99fdSEd Maste 	}								\
350c43e99fdSEd Maste 									\
351c43e99fdSEd Maste 	*pnumber = number;						\
352c43e99fdSEd Maste 									\
353c43e99fdSEd Maste 	return (int)(len);						\
354c43e99fdSEd Maste } while (0)
355c43e99fdSEd Maste 
356c43e99fdSEd Maste /* Internal: decode an integer from an evbuffer, without draining it.
357c43e99fdSEd Maste  *  Only integers up to 32-bits are supported.
358c43e99fdSEd Maste  *
359c43e99fdSEd Maste  * @param evbuf the buffer to read from
360c43e99fdSEd Maste  * @param offset an index into the buffer at which we should start reading.
361c43e99fdSEd Maste  * @param pnumber a pointer to receive the integer.
362c43e99fdSEd Maste  * @return The length of the number as encoded, or -1 on error.
363c43e99fdSEd Maste  */
364c43e99fdSEd Maste 
365c43e99fdSEd Maste static int
decode_int_internal(ev_uint32_t * pnumber,struct evbuffer * evbuf,int offset)366c43e99fdSEd Maste decode_int_internal(ev_uint32_t *pnumber, struct evbuffer *evbuf, int offset)
367c43e99fdSEd Maste {
368c43e99fdSEd Maste 	ev_uint32_t number = 0;
369c43e99fdSEd Maste 	DECODE_INT_INTERNAL(number, 8, pnumber, evbuf, offset);
370c43e99fdSEd Maste }
371c43e99fdSEd Maste 
372c43e99fdSEd Maste static int
decode_int64_internal(ev_uint64_t * pnumber,struct evbuffer * evbuf,int offset)373c43e99fdSEd Maste decode_int64_internal(ev_uint64_t *pnumber, struct evbuffer *evbuf, int offset)
374c43e99fdSEd Maste {
375c43e99fdSEd Maste 	ev_uint64_t number = 0;
376c43e99fdSEd Maste 	DECODE_INT_INTERNAL(number, 16, pnumber, evbuf, offset);
377c43e99fdSEd Maste }
378c43e99fdSEd Maste 
379c43e99fdSEd Maste int
evtag_decode_int(ev_uint32_t * pnumber,struct evbuffer * evbuf)380c43e99fdSEd Maste evtag_decode_int(ev_uint32_t *pnumber, struct evbuffer *evbuf)
381c43e99fdSEd Maste {
382c43e99fdSEd Maste 	int res = decode_int_internal(pnumber, evbuf, 0);
383c43e99fdSEd Maste 	if (res != -1)
384c43e99fdSEd Maste 		evbuffer_drain(evbuf, res);
385c43e99fdSEd Maste 
386c43e99fdSEd Maste 	return (res == -1 ? -1 : 0);
387c43e99fdSEd Maste }
388c43e99fdSEd Maste 
389c43e99fdSEd Maste int
evtag_decode_int64(ev_uint64_t * pnumber,struct evbuffer * evbuf)390c43e99fdSEd Maste evtag_decode_int64(ev_uint64_t *pnumber, struct evbuffer *evbuf)
391c43e99fdSEd Maste {
392c43e99fdSEd Maste 	int res = decode_int64_internal(pnumber, evbuf, 0);
393c43e99fdSEd Maste 	if (res != -1)
394c43e99fdSEd Maste 		evbuffer_drain(evbuf, res);
395c43e99fdSEd Maste 
396c43e99fdSEd Maste 	return (res == -1 ? -1 : 0);
397c43e99fdSEd Maste }
398c43e99fdSEd Maste 
399c43e99fdSEd Maste int
evtag_peek(struct evbuffer * evbuf,ev_uint32_t * ptag)400c43e99fdSEd Maste evtag_peek(struct evbuffer *evbuf, ev_uint32_t *ptag)
401c43e99fdSEd Maste {
402c43e99fdSEd Maste 	return (decode_tag_internal(ptag, evbuf, 0 /* dodrain */));
403c43e99fdSEd Maste }
404c43e99fdSEd Maste 
405c43e99fdSEd Maste int
evtag_peek_length(struct evbuffer * evbuf,ev_uint32_t * plength)406c43e99fdSEd Maste evtag_peek_length(struct evbuffer *evbuf, ev_uint32_t *plength)
407c43e99fdSEd Maste {
408c43e99fdSEd Maste 	int res, len;
409c43e99fdSEd Maste 
410c43e99fdSEd Maste 	len = decode_tag_internal(NULL, evbuf, 0 /* dodrain */);
411c43e99fdSEd Maste 	if (len == -1)
412c43e99fdSEd Maste 		return (-1);
413c43e99fdSEd Maste 
414c43e99fdSEd Maste 	res = decode_int_internal(plength, evbuf, len);
415c43e99fdSEd Maste 	if (res == -1)
416c43e99fdSEd Maste 		return (-1);
417c43e99fdSEd Maste 
418c43e99fdSEd Maste 	*plength += res + len;
419c43e99fdSEd Maste 
420c43e99fdSEd Maste 	return (0);
421c43e99fdSEd Maste }
422c43e99fdSEd Maste 
423c43e99fdSEd Maste int
evtag_payload_length(struct evbuffer * evbuf,ev_uint32_t * plength)424c43e99fdSEd Maste evtag_payload_length(struct evbuffer *evbuf, ev_uint32_t *plength)
425c43e99fdSEd Maste {
426c43e99fdSEd Maste 	int res, len;
427c43e99fdSEd Maste 
428c43e99fdSEd Maste 	len = decode_tag_internal(NULL, evbuf, 0 /* dodrain */);
429c43e99fdSEd Maste 	if (len == -1)
430c43e99fdSEd Maste 		return (-1);
431c43e99fdSEd Maste 
432c43e99fdSEd Maste 	res = decode_int_internal(plength, evbuf, len);
433c43e99fdSEd Maste 	if (res == -1)
434c43e99fdSEd Maste 		return (-1);
435c43e99fdSEd Maste 
436c43e99fdSEd Maste 	return (0);
437c43e99fdSEd Maste }
438c43e99fdSEd Maste 
439c43e99fdSEd Maste /* just unmarshals the header and returns the length of the remaining data */
440c43e99fdSEd Maste 
441c43e99fdSEd Maste int
evtag_unmarshal_header(struct evbuffer * evbuf,ev_uint32_t * ptag)442c43e99fdSEd Maste evtag_unmarshal_header(struct evbuffer *evbuf, ev_uint32_t *ptag)
443c43e99fdSEd Maste {
444c43e99fdSEd Maste 	ev_uint32_t len;
445c43e99fdSEd Maste 
446c43e99fdSEd Maste 	if (decode_tag_internal(ptag, evbuf, 1 /* dodrain */) == -1)
447c43e99fdSEd Maste 		return (-1);
448c43e99fdSEd Maste 	if (evtag_decode_int(&len, evbuf) == -1)
449c43e99fdSEd Maste 		return (-1);
450c43e99fdSEd Maste 
451c43e99fdSEd Maste 	if (evbuffer_get_length(evbuf) < len)
452c43e99fdSEd Maste 		return (-1);
453c43e99fdSEd Maste 
454c43e99fdSEd Maste 	return (len);
455c43e99fdSEd Maste }
456c43e99fdSEd Maste 
457c43e99fdSEd Maste int
evtag_consume(struct evbuffer * evbuf)458c43e99fdSEd Maste evtag_consume(struct evbuffer *evbuf)
459c43e99fdSEd Maste {
460c43e99fdSEd Maste 	int len;
461c43e99fdSEd Maste 	if ((len = evtag_unmarshal_header(evbuf, NULL)) == -1)
462c43e99fdSEd Maste 		return (-1);
463c43e99fdSEd Maste 	evbuffer_drain(evbuf, len);
464c43e99fdSEd Maste 
465c43e99fdSEd Maste 	return (0);
466c43e99fdSEd Maste }
467c43e99fdSEd Maste 
468c43e99fdSEd Maste /* Reads the data type from an event buffer */
469c43e99fdSEd Maste 
470c43e99fdSEd Maste int
evtag_unmarshal(struct evbuffer * src,ev_uint32_t * ptag,struct evbuffer * dst)471c43e99fdSEd Maste evtag_unmarshal(struct evbuffer *src, ev_uint32_t *ptag, struct evbuffer *dst)
472c43e99fdSEd Maste {
473c43e99fdSEd Maste 	int len;
474c43e99fdSEd Maste 
475c43e99fdSEd Maste 	if ((len = evtag_unmarshal_header(src, ptag)) == -1)
476c43e99fdSEd Maste 		return (-1);
477c43e99fdSEd Maste 
478c43e99fdSEd Maste 	if (evbuffer_add(dst, evbuffer_pullup(src, len), len) == -1)
479c43e99fdSEd Maste 		return (-1);
480c43e99fdSEd Maste 
481c43e99fdSEd Maste 	evbuffer_drain(src, len);
482c43e99fdSEd Maste 
483c43e99fdSEd Maste 	return (len);
484c43e99fdSEd Maste }
485c43e99fdSEd Maste 
486c43e99fdSEd Maste /* Marshaling for integers */
487c43e99fdSEd Maste 
488c43e99fdSEd Maste int
evtag_unmarshal_int(struct evbuffer * evbuf,ev_uint32_t need_tag,ev_uint32_t * pinteger)489c43e99fdSEd Maste evtag_unmarshal_int(struct evbuffer *evbuf, ev_uint32_t need_tag,
490c43e99fdSEd Maste     ev_uint32_t *pinteger)
491c43e99fdSEd Maste {
492c43e99fdSEd Maste 	ev_uint32_t tag;
493c43e99fdSEd Maste 	ev_uint32_t len;
494c43e99fdSEd Maste 	int result;
495c43e99fdSEd Maste 
496c43e99fdSEd Maste 	if (decode_tag_internal(&tag, evbuf, 1 /* dodrain */) == -1)
497c43e99fdSEd Maste 		return (-1);
498c43e99fdSEd Maste 	if (need_tag != tag)
499c43e99fdSEd Maste 		return (-1);
500c43e99fdSEd Maste 	if (evtag_decode_int(&len, evbuf) == -1)
501c43e99fdSEd Maste 		return (-1);
502c43e99fdSEd Maste 
503c43e99fdSEd Maste 	if (evbuffer_get_length(evbuf) < len)
504c43e99fdSEd Maste 		return (-1);
505c43e99fdSEd Maste 
506c43e99fdSEd Maste 	result = decode_int_internal(pinteger, evbuf, 0);
507c43e99fdSEd Maste 	evbuffer_drain(evbuf, len);
508c43e99fdSEd Maste 	if (result < 0 || (size_t)result > len) /* XXX Should this be != rather than > ?*/
509c43e99fdSEd Maste 		return (-1);
510c43e99fdSEd Maste 	else
511c43e99fdSEd Maste 		return result;
512c43e99fdSEd Maste }
513c43e99fdSEd Maste 
514c43e99fdSEd Maste int
evtag_unmarshal_int64(struct evbuffer * evbuf,ev_uint32_t need_tag,ev_uint64_t * pinteger)515c43e99fdSEd Maste evtag_unmarshal_int64(struct evbuffer *evbuf, ev_uint32_t need_tag,
516c43e99fdSEd Maste     ev_uint64_t *pinteger)
517c43e99fdSEd Maste {
518c43e99fdSEd Maste 	ev_uint32_t tag;
519c43e99fdSEd Maste 	ev_uint32_t len;
520c43e99fdSEd Maste 	int result;
521c43e99fdSEd Maste 
522c43e99fdSEd Maste 	if (decode_tag_internal(&tag, evbuf, 1 /* dodrain */) == -1)
523c43e99fdSEd Maste 		return (-1);
524c43e99fdSEd Maste 	if (need_tag != tag)
525c43e99fdSEd Maste 		return (-1);
526c43e99fdSEd Maste 	if (evtag_decode_int(&len, evbuf) == -1)
527c43e99fdSEd Maste 		return (-1);
528c43e99fdSEd Maste 
529c43e99fdSEd Maste 	if (evbuffer_get_length(evbuf) < len)
530c43e99fdSEd Maste 		return (-1);
531c43e99fdSEd Maste 
532c43e99fdSEd Maste 	result = decode_int64_internal(pinteger, evbuf, 0);
533c43e99fdSEd Maste 	evbuffer_drain(evbuf, len);
534c43e99fdSEd Maste 	if (result < 0 || (size_t)result > len) /* XXX Should this be != rather than > ?*/
535c43e99fdSEd Maste 		return (-1);
536c43e99fdSEd Maste 	else
537c43e99fdSEd Maste 		return result;
538c43e99fdSEd Maste }
539c43e99fdSEd Maste 
540c43e99fdSEd Maste /* Unmarshal a fixed length tag */
541c43e99fdSEd Maste 
542c43e99fdSEd Maste int
evtag_unmarshal_fixed(struct evbuffer * src,ev_uint32_t need_tag,void * data,size_t len)543c43e99fdSEd Maste evtag_unmarshal_fixed(struct evbuffer *src, ev_uint32_t need_tag, void *data,
544c43e99fdSEd Maste     size_t len)
545c43e99fdSEd Maste {
546c43e99fdSEd Maste 	ev_uint32_t tag;
547c43e99fdSEd Maste 	int tag_len;
548c43e99fdSEd Maste 
549c43e99fdSEd Maste 	/* Now unmarshal a tag and check that it matches the tag we want */
550c43e99fdSEd Maste 	if ((tag_len = evtag_unmarshal_header(src, &tag)) < 0 ||
551c43e99fdSEd Maste 	    tag != need_tag)
552c43e99fdSEd Maste 		return (-1);
553c43e99fdSEd Maste 
554c43e99fdSEd Maste 	if ((size_t)tag_len != len)
555c43e99fdSEd Maste 		return (-1);
556c43e99fdSEd Maste 
557c43e99fdSEd Maste 	evbuffer_remove(src, data, len);
558c43e99fdSEd Maste 	return (0);
559c43e99fdSEd Maste }
560c43e99fdSEd Maste 
561c43e99fdSEd Maste int
evtag_unmarshal_string(struct evbuffer * evbuf,ev_uint32_t need_tag,char ** pstring)562c43e99fdSEd Maste evtag_unmarshal_string(struct evbuffer *evbuf, ev_uint32_t need_tag,
563c43e99fdSEd Maste     char **pstring)
564c43e99fdSEd Maste {
565c43e99fdSEd Maste 	ev_uint32_t tag;
566c43e99fdSEd Maste 	int tag_len;
567c43e99fdSEd Maste 
568c43e99fdSEd Maste 	if ((tag_len = evtag_unmarshal_header(evbuf, &tag)) == -1 ||
569c43e99fdSEd Maste 	    tag != need_tag)
570c43e99fdSEd Maste 		return (-1);
571c43e99fdSEd Maste 
572c43e99fdSEd Maste 	*pstring = mm_malloc(tag_len + 1);
573c43e99fdSEd Maste 	if (*pstring == NULL) {
574c43e99fdSEd Maste 		event_warn("%s: malloc", __func__);
575c43e99fdSEd Maste 		return -1;
576c43e99fdSEd Maste 	}
577c43e99fdSEd Maste 	evbuffer_remove(evbuf, *pstring, tag_len);
578c43e99fdSEd Maste 	(*pstring)[tag_len] = '\0';
579c43e99fdSEd Maste 
580c43e99fdSEd Maste 	return (0);
581c43e99fdSEd Maste }
582c43e99fdSEd Maste 
583c43e99fdSEd Maste int
evtag_unmarshal_timeval(struct evbuffer * evbuf,ev_uint32_t need_tag,struct timeval * ptv)584c43e99fdSEd Maste evtag_unmarshal_timeval(struct evbuffer *evbuf, ev_uint32_t need_tag,
585c43e99fdSEd Maste     struct timeval *ptv)
586c43e99fdSEd Maste {
587c43e99fdSEd Maste 	ev_uint32_t tag;
588c43e99fdSEd Maste 	ev_uint32_t integer;
589c43e99fdSEd Maste 	int len, offset, offset2;
590c43e99fdSEd Maste 	int result = -1;
591c43e99fdSEd Maste 
592c43e99fdSEd Maste 	if ((len = evtag_unmarshal_header(evbuf, &tag)) == -1)
593c43e99fdSEd Maste 		return (-1);
594c43e99fdSEd Maste 	if (tag != need_tag)
595c43e99fdSEd Maste 		goto done;
596c43e99fdSEd Maste 	if ((offset = decode_int_internal(&integer, evbuf, 0)) == -1)
597c43e99fdSEd Maste 		goto done;
598c43e99fdSEd Maste 	ptv->tv_sec = integer;
599c43e99fdSEd Maste 	if ((offset2 = decode_int_internal(&integer, evbuf, offset)) == -1)
600c43e99fdSEd Maste 		goto done;
601c43e99fdSEd Maste 	ptv->tv_usec = integer;
602c43e99fdSEd Maste 	if (offset + offset2 > len) /* XXX Should this be != instead of > ? */
603c43e99fdSEd Maste 		goto done;
604c43e99fdSEd Maste 
605c43e99fdSEd Maste 	result = 0;
606c43e99fdSEd Maste  done:
607c43e99fdSEd Maste 	evbuffer_drain(evbuf, len);
608c43e99fdSEd Maste 	return result;
609c43e99fdSEd Maste }
610