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