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