From 4987a4455a4776091ed047e0a6d27eb0b42523a2 Mon Sep 17 00:00:00 2001 From: laforge Date: Thu, 13 Jun 2002 12:55:21 +0000 Subject: add support for PCAP output --- ulogd/extensions/ulogd_BASE.c | 25 +++-- ulogd/extensions/ulogd_PCAP.c | 228 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 245 insertions(+), 8 deletions(-) create mode 100644 ulogd/extensions/ulogd_PCAP.c (limited to 'ulogd/extensions') diff --git a/ulogd/extensions/ulogd_BASE.c b/ulogd/extensions/ulogd_BASE.c index 852405e..51568be 100644 --- a/ulogd/extensions/ulogd_BASE.c +++ b/ulogd/extensions/ulogd_BASE.c @@ -1,4 +1,4 @@ -/* ulogd_MAC.c, Version $Revision: 1.10 $ +/* ulogd_MAC.c, Version $Revision: 1.11 $ * * ulogd interpreter plugin for * o MAC addresses @@ -26,7 +26,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * $Id: ulogd_BASE.c,v 1.10 2001/09/01 11:51:54 laforge Exp $ + * $Id: ulogd_BASE.c,v 1.11 2002/04/27 19:45:27 laforge Exp $ * */ @@ -42,12 +42,16 @@ /*********************************************************************** * Raw header ***********************************************************************/ -static ulog_iret_t mac_rets[1] = { +static ulog_iret_t raw_rets[] = { { NULL, NULL, 0, ULOGD_RET_STRING, ULOGD_RETF_FREE, "raw.mac", { ptr: NULL } }, + { NULL, NULL, 0, ULOGD_RET_RAW, ULOGD_RETF_NONE, "raw.pkt", + { ptr: NULL } }, + { NULL, NULL, 0, ULOGD_RET_UINT32, ULOGD_RETF_NONE, "raw.pktlen", + { ui32: 0 } }, }; -static ulog_iret_t *_interp_mac(struct ulog_interpreter *ip, +static ulog_iret_t *_interp_raw(struct ulog_interpreter *ip, ulog_packet_msg_t *pkt) { unsigned char *p; @@ -69,10 +73,15 @@ static ulog_iret_t *_interp_mac(struct ulog_interpreter *ip, sprintf(buf, "%s%02x%c", oldbuf, *p, i==pkt->mac_len-1 ? ' ':':'); ret[0].value.ptr = buf; ret[0].flags |= ULOGD_RETF_VALID; - return ret; - } - return NULL; + + /* include pointer to raw ipv4 packet */ + ret[1].value.ptr = pkt->payload; + ret[1].flags |= ULOGD_RETF_VALID; + ret[2].value.ui32 = pkt->data_len; + ret[2].flags |= ULOGD_RETF_VALID; + + return ret; } /*********************************************************************** @@ -375,7 +384,7 @@ static ulog_iret_t *_interp_ahesp(struct ulog_interpreter *ip, static ulog_interpreter_t base_ip[] = { - { NULL, "raw", 0, &_interp_mac, 1, &mac_rets }, + { NULL, "raw", 0, &_interp_raw, 3, &raw_rets }, { NULL, "oob", 0, &_interp_oob, 6, &oob_rets }, { NULL, "ip", 0, &_interp_iphdr, 10, &iphdr_rets }, { NULL, "tcp", 0, &_interp_tcphdr, 12, &tcphdr_rets }, diff --git a/ulogd/extensions/ulogd_PCAP.c b/ulogd/extensions/ulogd_PCAP.c new file mode 100644 index 0000000..547982e --- /dev/null +++ b/ulogd/extensions/ulogd_PCAP.c @@ -0,0 +1,228 @@ +/* ulogd_PCAP.c, Version $Revision: 1.9 $ + * + * ulogd output target for writing pcap-style files (like tcpdump) + * + * FIXME: descr. + * + * + * (C) 2002 by Harald Welte + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation + * + * 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 + * + * $Id: ulogd_LOGEMU.c,v 1.9 2002/04/27 19:45:51 laforge Exp $ + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "ulogd.h" +#include "conffile.h" + +#ifndef ULOGD_PCAP_DEFAULT +#define ULOGD_PCAP_DEFAULT "/var/log/ulogd.pcap" +#endif + +#ifndef ULOGD_PCAP_SYNC_DEFAULT +#define ULOGD_PCAP_SYNC_DEFAULT 0 +#endif + +#define NIPQUAD(addr) \ + ((unsigned char *)&addr)[0], \ + ((unsigned char *)&addr)[1], \ + ((unsigned char *)&addr)[2], \ + ((unsigned char *)&addr)[3] + +static config_entry_t pcapf_ce = { NULL, "pcapfile", CONFIG_TYPE_STRING, + CONFIG_OPT_NONE, 0, + { string: ULOGD_PCAP_DEFAULT } }; + +static config_entry_t pcapsync_ce = { &pcapf_ce, "pcapsync", + CONFIG_TYPE_INT, CONFIG_OPT_NONE, 0, + { value: ULOGD_PCAP_SYNC_DEFAULT } + }; + +static FILE *of = NULL; + +static char hostname[255]; + +struct intr_id { + char* name; + unsigned int id; +}; + +#define INTR_IDS 5 +static struct intr_id intr_ids[INTR_IDS] = { + { "raw.pkt", 0 }, + { "raw.pktlen", 0 }, + { "ip.totlen", 0 }, + { "oob.time.sec", 0 }, + { "oob.time.usec", 0 }, +}; + +#define GET_VALUE(x) ulogd_keyh[intr_ids[x].id].interp->result[ulogd_keyh[intr_ids[x].id].offset].value +#define GET_FLAGS(x) ulogd_keyh[intr_ids[x].id].interp->result[ulogd_keyh[intr_ids[x].id].offset].flags + +int _output_pcap(ulog_iret_t *res) +{ + ulog_iret_t *ret; + struct pcap_pkthdr pchdr; + + pchdr.caplen = GET_VALUE(1).ui32; + pchdr.len = GET_VALUE(2).ui32; + + if (GET_FLAGS(3) & ULOGD_RETF_VALID + && GET_FLAGS(4) & ULOGD_RETF_VALID) { + pchdr.ts.tv_sec = GET_VALUE(3).ui32; + pchdr.ts.tv_usec = GET_VALUE(4).ui32; + } else { + /* use current system time */ + gettimeofday(&pchdr.ts, NULL); + } + + if (fwrite(&pchdr, sizeof(pchdr), 1, of) != 1) { + ulogd_log(ULOGD_ERROR, "Error during write: %s\n", + strerror(errno)); + return 1; + } + if (fwrite(GET_VALUE(0).ptr, pchdr.caplen, 1, of) != 1) { + ulogd_log(ULOGD_ERROR, "Error during write: %s\n", + strerror(errno)); + return 1; + } + + if (pcapf_ce.u.value) + fflush(of); + + return 0; +} + +/* stolen from libpcap savefile.c */ +#define LINKTYPE_RAW 101 +#define TCPDUMP_MAGIC 0xa1b2c3d4 + +static int write_pcap_header(void) +{ + struct pcap_file_header pcfh; + int ret; + + pcfh.magic = TCPDUMP_MAGIC; + pcfh.version_major = PCAP_VERSION_MAJOR; + pcfh.version_minor = PCAP_VERSION_MINOR; + pcfh.thiszone = timezone; + pcfh.sigfigs = 0; + pcfh.snaplen = 64 * 1024; /* we don't know the length in advance */ + pcfh.linktype = LINKTYPE_RAW; + + ret = fwrite(&pcfh, sizeof(pcfh), 1, of); + fflush(of); + + return ret; +} + +/* get all key id's for the keys we are intrested in */ +static int get_ids(void) +{ + int i; + struct intr_id *cur_id; + + for (i = 0; i < INTR_IDS; i++) { + cur_id = &intr_ids[i]; + cur_id->id = keyh_getid(cur_id->name); + if (!cur_id->id) { + ulogd_log(ULOGD_ERROR, + "Cannot resolve keyhash id for %s\n", + cur_id->name); + return 1; + } + } + return 0; +} + +void append_create_outfile(void) { + struct stat st_dummy; + + if (stat(pcapf_ce.u.string, &st_dummy)) { + of = fopen(pcapf_ce.u.string, "w"); + if (!of) { + ulogd_log(ULOGD_FATAL, "can't open pcap file: %s\n", + strerror(errno)); + exit(2); + } + if (!write_pcap_header()) { + ulogd_log(ULOGD_FATAL, "can't write pcap header: %s\n", + strerror(errno)); + exit(2); + } + } else { + of = fopen(pcapf_ce.u.string, "a"); + if (!of) { + ulogd_log(ULOGD_FATAL, "can't open pcap file: %s\n", + strerror(errno)); + exit(2); + } + } +} + +void sighup_handler_pcap(int signal) +{ + switch (signal) { + case SIGHUP: + ulogd_log(ULOGD_NOTICE, "pcap: reopening capture file\n"); + fclose(of); + append_create_outfile(); + break; + default: + break; + } +} + + +static ulog_output_t logemu_op[] = { + { NULL, "pcap", &_output_pcap, &sighup_handler_pcap }, + { NULL, "", NULL, NULL }, +}; + +/* register output plugin with ulogd */ +static void _logemu_reg_op(void) +{ + ulog_output_t *op = logemu_op; + ulog_output_t *p; + + for (p = op; p->output; p++) + register_output(p); +} + +void _init(void) +{ + /* FIXME: error handling */ + config_register_key(&pcapsync_ce); + config_parse_file(0); + +#ifdef DEBUG_PCAP + of = stdout; +#else + append_create_outfile(); +#endif + if (get_ids()) { + ulogd_log(ULOGD_ERROR, "can't resolve all keyhash id's\n"); + } + + _logemu_reg_op(); +} -- cgit v1.2.3