/*
* Copyright (c) 2003, 2004 Niels Provos <provos@citi.umich.edu>
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <sys/types.h>
#include <sys/param.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <sys/ioctl.h>
#include <sys/tree.h>
#include <sys/queue.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include <event.h>
#include <pcap.h>
#include <dnet.h>
#include "tagging.h"
struct evbuffer *_buf;
void
tagging_init()
{
_buf = evbuffer_new();
}
/*
* We encode integer's by nibbles; the first nibble contains the number
* of significant nibbles - 1; this allows us to encode up to 64-bit
* integers. This function is byte-order independent.
*/
void
encode_int(struct evbuffer *evbuf, uint32_t number)
{
int off = 1, nibbles = 0;
uint8_t data[5];
memset(data, 0, sizeof(data));
while (number) {
if (off & 0x1)
data[off/2] = (data[off/2] & 0xf0) | (number & 0x0f);
else
data[off/2] = (data[off/2] & 0x0f) |
((number & 0x0f) << 4);
number >>= 4;
off++;
}
if (off > 2)
nibbles = off - 2;
/* Off - 1 is the number of encoded nibbles */
data[0] = (data[0] & 0x0f) | ((nibbles & 0x0f) << 4);
evbuffer_add(evbuf, data, (off + 1) / 2);
}
/*
* Marshal a data type, the general format is as follows:
*
* tag number: one byte; length: var bytes; payload: var bytes
*/
void
tag_marshal(struct evbuffer *evbuf, uint8_t tag, void *data, uint16_t len)
{
evbuffer_add(evbuf, &tag, sizeof(tag));
encode_int(evbuf, len);
evbuffer_add(evbuf, data, len);
}
/* Marshaling for integers */
void
tag_marshal_int(struct evbuffer *evbuf, uint8_t tag, uint32_t integer)
{
evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
encode_int(_buf, integer);
evbuffer_add(evbuf, &tag, sizeof(tag));
encode_int(evbuf, EVBUFFER_LENGTH(_buf));
evbuffer_add_buffer(evbuf, _buf);
}
void
tag_marshal_string(struct evbuffer *buf, uint8_t tag, char *string)
{
tag_marshal(buf, tag, string, strlen(string));
}
void
tag_marshal_timeval(struct evbuffer *evbuf, uint8_t tag, struct timeval *tv)
{
evbuffer_drain(_buf, EVBUFFER_LENGTH(_buf));
encode_int(_buf, tv->tv_sec);
encode_int(_buf, tv->tv_usec);
tag_marshal(evbuf, tag, EVBUFFER_DATA(_buf),
EVBUFFER_LENGTH(_buf));
}
void
tag_marshal_record(struct evbuffer *evbuf, uint8_t tag, struct record *record)
{
struct evbuffer *tmp = evbuffer_new();
record_marshal(tmp, record);
tag_marshal(evbuf, tag, EVBUFFER_DATA(tmp), EVBUFFER_LENGTH(tmp));
evbuffer_free(tmp);
}
/*
* Functions for un/marshaling dnet's struct addr; we create a tagged
* stream to save space. Otherwise, we would have pay the overhead of
* IPv6 address sizes for every kind of address.
*/
#define MARSHAL(tag, what) do { \
tag_marshal(evbuf, tag, &(what), sizeof(what)); \
} while (0)
void
addr_marshal(struct evbuffer *evbuf, struct addr *addr)
{
tag_marshal_int(evbuf, ADDR_TYPE, addr->addr_type);
tag_marshal_int(evbuf, ADDR_BITS, addr->addr_bits);
switch (addr->addr_type) {
case ADDR_TYPE_ETH:
MARSHAL(ADDR_ADDR, addr->addr_eth);
break;
case ADDR_TYPE_IP:
MARSHAL(ADDR_ADDR, addr->addr_ip);
break;
case ADDR_TYPE_IP6:
MARSHAL(ADDR_ADDR, addr->addr_ip6);
break;
}
}
/*
* Functions to un/marshal records.
*/
void
record_marshal(struct evbuffer *evbuf, struct record *record)
{
struct evbuffer *addr = evbuffer_new();
struct hash *hash;
if (timerisset(&record->tv_start))
tag_marshal_timeval(evbuf, REC_TV_START, &record->tv_start);
if (timerisset(&record->tv_end))
tag_marshal_timeval(evbuf, REC_TV_END, &record->tv_end);
/* Encode an address */
evbuffer_drain(addr, EVBUFFER_LENGTH(addr));
addr_marshal(addr, &record->src);
tag_marshal(evbuf, REC_SRC, EVBUFFER_DATA(addr), EVBUFFER_LENGTH(addr));
evbuffer_drain(addr, EVBUFFER_LENGTH(addr));
addr_marshal(addr, &record->dst);
tag_marshal(evbuf, REC_DST, EVBUFFER_DATA(addr), EVBUFFER_LENGTH(addr));
tag_marshal_int(evbuf, REC_SRC_PORT, record->src_port);
tag_marshal_int(evbuf, REC_DST_PORT, record->dst_port);
tag_marshal_int(evbuf, REC_PROTO, record->proto);
tag_marshal_int(evbuf, REC_STATE, record->state);
if (record->os_fp != NULL)
tag_marshal_string(evbuf, REC_OS_FP, record->os_fp);
TAILQ_FOREACH(hash, &record->hashes, next)
tag_marshal(evbuf, REC_HASH, hash->digest, sizeof(hash->digest));
if (record->bytes)
tag_marshal_int(evbuf, REC_BYTES, record->bytes);
if (record->flags)
tag_marshal_int(evbuf, REC_FLAGS, record->flags);
evbuffer_free(addr);
}
syntax highlighted by Code2HTML, v. 0.9.1