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