blob: c8db059515afae2c62f06c4a27468d0a0810db91 [file] [log] [blame] [raw]
/*
* record.c
*
* Copyright (c) 2000 Dug Song <dugsong@monkey.org>
*
* $Id: record.c,v 1.10 2001/03/15 08:33:04 dugsong Exp $
*/
#include "config.h"
#include <sys/types.h>
#include <netinet/in.h>
#include <rpc/rpc.h>
#include <stdio.h>
#include <time.h>
#if 0
#include <md5.h>
#else
#include <openssl/md5.h>
#define MD5Init MD5_Init
#define MD5Update MD5_Update
#define MD5Final MD5_Final
#endif
#ifdef HAVE_DB_185_H
#define DB_LIBRARY_COMPATIBILITY_API
#include <db_185.h>
#elif HAVE_DB_H
#include <db.h>
#endif
#include <libnet.h>
#include "options.h"
#include "record.h"
struct rec {
time_t time;
in_addr_t src;
in_addr_t dst;
u_int proto;
u_short sport;
u_short dport;
struct netobj name;
struct netobj data;
};
static DB *db;
static int
xdr_rec(XDR *xdrs, struct rec *rec)
{
if (xdr_u_long(xdrs, (u_long *)&rec->time) &&
xdr_u_long(xdrs, (u_long *)&rec->src) &&
xdr_u_long(xdrs, (u_long *)&rec->dst) &&
xdr_u_int(xdrs, &rec->proto) &&
xdr_u_short(xdrs, &rec->sport) &&
xdr_u_short(xdrs, &rec->dport) &&
xdr_netobj(xdrs, &rec->name) &&
xdr_netobj(xdrs, &rec->data)) {
return (1);
}
return (0);
}
static void
record_print(struct rec *rec)
{
struct tm *tm;
char *srcp, *dstp, *protop, tstr[24], spstr[8], dpstr[8];
struct protoent *pr;
tm = localtime(&rec->time);
strftime(tstr, sizeof(tstr), "%F %T", tm);
srcp = libnet_addr2name4(rec->src, Opt_dns);
dstp = libnet_addr2name4(rec->dst, Opt_dns);
if ((pr = getprotobynumber(rec->proto)) == NULL)
protop = "unknown";
else
protop = pr->p_name;
snprintf(spstr, sizeof(spstr), "%d", rec->sport);
snprintf(dpstr, sizeof(dpstr), "%d", rec->dport);
printf("-----------------\n");
printf("%s %s %s%s%s -> %s%s%s (%.*s)\n",
tstr, protop,
srcp, rec->sport ? "." : "", rec->sport ? spstr : "",
dstp, rec->dport ? "." : "", rec->dport ? dpstr : "",
(int) rec->name.n_len, rec->name.n_bytes);
fwrite(rec->data.n_bytes, 1, rec->data.n_len, stdout);
printf("\n");
fflush(stdout);
}
static DBT *
record_hash(struct rec *rec)
{
static DBT key;
static u_char hash[16];
MD5_CTX ctx;
/* Unique key: src/dst IPs, decode type, decode data. */
MD5Init(&ctx);
MD5Update(&ctx, (u_char *) &rec->src, sizeof(rec->src));
MD5Update(&ctx, (u_char *) &rec->dst, sizeof(rec->dst));
MD5Update(&ctx, rec->name.n_bytes, rec->name.n_len);
MD5Update(&ctx, rec->data.n_bytes, rec->data.n_len);
MD5Final(hash, &ctx);
key.data = hash;
key.size = sizeof(hash);
return (&key);
}
static int
record_save(struct rec *rec)
{
DBT *key, data;
XDR xdrs;
u_char buf[2048];
xdrmem_create(&xdrs, (char *)buf, sizeof(buf), XDR_ENCODE);
if (!xdr_rec(&xdrs, rec))
return (0);
data.data = buf;
data.size = xdr_getpos(&xdrs);
xdr_destroy(&xdrs);
key = record_hash(rec);
if (db->put(db, key, &data, R_NOOVERWRITE) == 0)
db->sync(db, 0);
return (1);
}
void
record_dump(void)
{
DBT key, data;
XDR xdrs;
struct rec rec;
while (db->seq(db, &key, &data, R_NEXT) == 0) {
memset(&rec, 0, sizeof(rec));
xdrmem_create(&xdrs, data.data, data.size, XDR_DECODE);
if (xdr_rec(&xdrs, &rec)) {
record_print(&rec);
}
xdr_destroy(&xdrs);
}
}
int
record_init(char *file)
{
int flags, mode;
if (Opt_read) {
flags = O_RDONLY;
mode = 0;
}
else {
flags = O_RDWR|O_CREAT;
mode = S_IRUSR|S_IWUSR;
}
if ((db = dbopen(file, flags, mode, DB_BTREE, NULL)) == NULL)
return (0);
return (1);
}
int
record(in_addr_t src, in_addr_t dst, int proto, u_short sport, u_short dport,
char *name, u_char *buf, int len)
{
struct rec rec;
rec.time = time(NULL);
rec.src = src;
rec.dst = dst;
rec.proto = proto;
rec.sport = sport;
rec.dport = dport;
rec.name.n_bytes = name;
rec.name.n_len = strlen(name);
rec.data.n_bytes = (char *)buf;
rec.data.n_len = len;
if (!Opt_read && !Opt_write)
record_print(&rec);
record_save(&rec);
return (1);
}
void
record_close(void)
{
db->close(db);
}