1/*	$NetBSD$	*/
2/*
3 * Copyright (c) 2003, 2004 Niels Provos <provos@citi.umich.edu>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 *    derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#ifdef HAVE_SYS_TYPES_H
34#include <sys/types.h>
35#endif
36#ifdef HAVE_SYS_PARAM_H
37#include <sys/param.h>
38#endif
39
40#ifdef WIN32
41#define WIN32_LEAN_AND_MEAN
42#include <winsock2.h>
43#include <windows.h>
44#undef WIN32_LEAN_AND_MEAN
45#else
46#include <sys/ioctl.h>
47#endif
48
49#include <sys/queue.h>
50#ifdef HAVE_SYS_TIME_H
51#include <sys/time.h>
52#endif
53
54#include <errno.h>
55#include <stdio.h>
56#include <stdlib.h>
57#include <string.h>
58#ifndef WIN32
59#include <syslog.h>
60#endif
61#ifdef HAVE_UNISTD_H
62#include <unistd.h>
63#endif
64
65#include "event.h"
66#include "evutil.h"
67#include "log.h"
68
69int evtag_decode_int(ev_uint32_t *pnumber, struct evbuffer *evbuf);
70int evtag_encode_tag(struct evbuffer *evbuf, ev_uint32_t tag);
71int evtag_decode_tag(ev_uint32_t *ptag, struct evbuffer *evbuf);
72
73static struct evbuffer *_buf;	/* not thread safe */
74
75void
76evtag_init(void)
77{
78	if (_buf != NULL)
79		return;
80
81	if ((_buf = evbuffer_new()) == NULL)
82		event_err(1, "%s: malloc", __func__);
83}
84
85/*
86 * We encode integer's by nibbles; the first nibble contains the number
87 * of significant nibbles - 1;  this allows us to encode up to 64-bit
88 * integers.  This function is byte-order independent.
89 */
90
91void
92encode_int(struct evbuffer *evbuf, ev_uint32_t number)
93{
94	int off = 1, nibbles = 0;
95	ev_uint8_t data[5];
96
97	memset(data, 0, sizeof(ev_uint32_t)+1);
98	while (number) {
99		if (off & 0x1)
100			data[off/2] = (data[off/2] & 0xf0) | (number & 0x0f);
101		else
102			data[off/2] = (data[off/2] & 0x0f) |
103			    ((number & 0x0f) << 4);
104		number >>= 4;
105		off++;
106	}
107
108	if (off > 2)
109		nibbles = off - 2;
110
111	/* Off - 1 is the number of encoded nibbles */
112	data[0] = (data[0] & 0x0f) | ((nibbles & 0x0f) << 4);
113
114	evbuffer_add(evbuf, data, (off + 1) / 2);
115}
116
117/*
118 * Support variable length encoding of tags; we use the high bit in each
119 * octet as a continuation signal.
120 */
121
122int
123evtag_encode_tag(struct evbuffer *evbuf, ev_uint32_t tag)
124{
125	int bytes = 0;
126	ev_uint8_t data[5];
127
128	memset(data, 0, sizeof(data));
129	do {
130		ev_uint8_t lower = tag & 0x7f;
131		tag >>= 7;
132
133		if (tag)
134			lower |= 0x80;
135
136		data[bytes++] = lower;
137	} while (tag);
138
139	if (evbuf != NULL)
140		evbuffer_add(evbuf, data, bytes);
141
142	return (bytes);
143}
144
145static int
146decode_tag_internal(ev_uint32_t *ptag, struct evbuffer *evbuf, int dodrain)
147{
148	ev_uint32_t number = 0;
149	ev_uint8_t *data = EVBUFFER_DATA(evbuf);
150	int len = EVBUFFER_LENGTH(evbuf);
151	int count = 0, shift = 0, done = 0;
152
153	while (count++ < len) {
154		ev_uint8_t lower = *data++;
155		number |= (lower & 0x7f) << shift;
156		shift += 7;
157
158		if (!(lower & 0x80)) {
159			done = 1;
160			break;
161		}
162	}
163
164	if (!done)
165		return (-1);
166
167	if (dodrain)
168		evbuffer_drain(evbuf, count);
169
170	if (ptag != NULL)
171		*ptag = number;
172
173	return (count);
174}
175
176int
177evtag_decode_tag(ev_uint32_t *ptag, struct evbuffer *evbuf)
178{
179	return (decode_tag_internal(ptag, evbuf, 1 /* dodrain */));
180}
181
182/*
183 * Marshal a data type, the general format is as follows:
184 *
185 * tag number: one byte; length: var bytes; payload: var bytes
186 */
187
188void
189evtag_marshal(struct evbuffer *evbuf, ev_uint32_t tag,
190    const void *data, ev_uint32_t len)
191{
192	evtag_encode_tag(evbuf, tag);
193	encode_int(evbuf, len);
194	evbuffer_add(evbuf, (void *)data, len);
195}
196
197/* Marshaling for integers */
198void
199evtag_marshal_int(struct evbuffer *evbuf, ev_uint32_t tag, ev_uint32_t integer)
200{
201	evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
202	encode_int(_buf, integer);
203
204	evtag_encode_tag(evbuf, tag);
205	encode_int(evbuf, EVBUFFER_LENGTH(_buf));
206	evbuffer_add_buffer(evbuf, _buf);
207}
208
209void
210evtag_marshal_string(struct evbuffer *buf, ev_uint32_t tag, const char *string)
211{
212	evtag_marshal(buf, tag, string, strlen(string));
213}
214
215void
216evtag_marshal_timeval(struct evbuffer *evbuf, ev_uint32_t tag, struct timeval *tv)
217{
218	evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
219
220	encode_int(_buf, tv->tv_sec);
221	encode_int(_buf, tv->tv_usec);
222
223	evtag_marshal(evbuf, tag, EVBUFFER_DATA(_buf),
224	    EVBUFFER_LENGTH(_buf));
225}
226
227static int
228decode_int_internal(ev_uint32_t *pnumber, struct evbuffer *evbuf, int dodrain)
229{
230	ev_uint32_t number = 0;
231	ev_uint8_t *data = EVBUFFER_DATA(evbuf);
232	int len = EVBUFFER_LENGTH(evbuf);
233	int nibbles = 0;
234
235	if (!len)
236		return (-1);
237
238	nibbles = ((data[0] & 0xf0) >> 4) + 1;
239	if (nibbles > 8 || (nibbles >> 1) + 1 > len)
240		return (-1);
241	len = (nibbles >> 1) + 1;
242
243	while (nibbles > 0) {
244		number <<= 4;
245		if (nibbles & 0x1)
246			number |= data[nibbles >> 1] & 0x0f;
247		else
248			number |= (data[nibbles >> 1] & 0xf0) >> 4;
249		nibbles--;
250	}
251
252	if (dodrain)
253		evbuffer_drain(evbuf, len);
254
255	*pnumber = number;
256
257	return (len);
258}
259
260int
261evtag_decode_int(ev_uint32_t *pnumber, struct evbuffer *evbuf)
262{
263	return (decode_int_internal(pnumber, evbuf, 1) == -1 ? -1 : 0);
264}
265
266int
267evtag_peek(struct evbuffer *evbuf, ev_uint32_t *ptag)
268{
269	return (decode_tag_internal(ptag, evbuf, 0 /* dodrain */));
270}
271
272int
273evtag_peek_length(struct evbuffer *evbuf, ev_uint32_t *plength)
274{
275	struct evbuffer tmp;
276	int res, len;
277
278	len = decode_tag_internal(NULL, evbuf, 0 /* dodrain */);
279	if (len == -1)
280		return (-1);
281
282	tmp = *evbuf;
283	tmp.buffer += len;
284	tmp.off -= len;
285
286	res = decode_int_internal(plength, &tmp, 0);
287	if (res == -1)
288		return (-1);
289
290	*plength += res + len;
291
292	return (0);
293}
294
295int
296evtag_payload_length(struct evbuffer *evbuf, ev_uint32_t *plength)
297{
298	struct evbuffer tmp;
299	int res, len;
300
301	len = decode_tag_internal(NULL, evbuf, 0 /* dodrain */);
302	if (len == -1)
303		return (-1);
304
305	tmp = *evbuf;
306	tmp.buffer += len;
307	tmp.off -= len;
308
309	res = decode_int_internal(plength, &tmp, 0);
310	if (res == -1)
311		return (-1);
312
313	return (0);
314}
315
316int
317evtag_consume(struct evbuffer *evbuf)
318{
319	ev_uint32_t len;
320	if (decode_tag_internal(NULL, evbuf, 1 /* dodrain */) == -1)
321		return (-1);
322	if (evtag_decode_int(&len, evbuf) == -1)
323		return (-1);
324	evbuffer_drain(evbuf, len);
325
326	return (0);
327}
328
329/* Reads the data type from an event buffer */
330
331int
332evtag_unmarshal(struct evbuffer *src, ev_uint32_t *ptag, struct evbuffer *dst)
333{
334	ev_uint32_t len;
335	ev_uint32_t integer;
336
337	if (decode_tag_internal(ptag, src, 1 /* dodrain */) == -1)
338		return (-1);
339	if (evtag_decode_int(&integer, src) == -1)
340		return (-1);
341	len = integer;
342
343	if (EVBUFFER_LENGTH(src) < len)
344		return (-1);
345
346	if (evbuffer_add(dst, EVBUFFER_DATA(src), len) == -1)
347		return (-1);
348
349	evbuffer_drain(src, len);
350
351	return (len);
352}
353
354/* Marshaling for integers */
355
356int
357evtag_unmarshal_int(struct evbuffer *evbuf, ev_uint32_t need_tag,
358    ev_uint32_t *pinteger)
359{
360	ev_uint32_t tag;
361	ev_uint32_t len;
362	ev_uint32_t integer;
363
364	if (decode_tag_internal(&tag, evbuf, 1 /* dodrain */) == -1)
365		return (-1);
366	if (need_tag != tag)
367		return (-1);
368	if (evtag_decode_int(&integer, evbuf) == -1)
369		return (-1);
370	len = integer;
371
372	if (EVBUFFER_LENGTH(evbuf) < len)
373		return (-1);
374
375	evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
376	if (evbuffer_add(_buf, EVBUFFER_DATA(evbuf), len) == -1)
377		return (-1);
378
379	evbuffer_drain(evbuf, len);
380
381	return (evtag_decode_int(pinteger, _buf));
382}
383
384/* Unmarshal a fixed length tag */
385
386int
387evtag_unmarshal_fixed(struct evbuffer *src, ev_uint32_t need_tag, void *data,
388    size_t len)
389{
390	ev_uint32_t tag;
391
392	/* Initialize this event buffer so that we can read into it */
393	evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
394
395	/* Now unmarshal a tag and check that it matches the tag we want */
396	if (evtag_unmarshal(src, &tag, _buf) == -1 || tag != need_tag)
397		return (-1);
398
399	if (EVBUFFER_LENGTH(_buf) != len)
400		return (-1);
401
402	memcpy(data, EVBUFFER_DATA(_buf), len);
403	return (0);
404}
405
406int
407evtag_unmarshal_string(struct evbuffer *evbuf, ev_uint32_t need_tag,
408    char **pstring)
409{
410	ev_uint32_t tag;
411
412	evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
413
414	if (evtag_unmarshal(evbuf, &tag, _buf) == -1 || tag != need_tag)
415		return (-1);
416
417	*pstring = calloc(EVBUFFER_LENGTH(_buf) + 1, 1);
418	if (*pstring == NULL)
419		event_err(1, "%s: calloc", __func__);
420	evbuffer_remove(_buf, *pstring, EVBUFFER_LENGTH(_buf));
421
422	return (0);
423}
424
425int
426evtag_unmarshal_timeval(struct evbuffer *evbuf, ev_uint32_t need_tag,
427    struct timeval *ptv)
428{
429	ev_uint32_t tag;
430	ev_uint32_t integer;
431
432	evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
433	if (evtag_unmarshal(evbuf, &tag, _buf) == -1 || tag != need_tag)
434		return (-1);
435
436	if (evtag_decode_int(&integer, _buf) == -1)
437		return (-1);
438	ptv->tv_sec = integer;
439	if (evtag_decode_int(&integer, _buf) == -1)
440		return (-1);
441	ptv->tv_usec = integer;
442
443	return (0);
444}
445