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