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