From 100b59f4bd207ac36aca39b6f011efbb132fe1cf Mon Sep 17 00:00:00 2001 From: laforge Date: Thu, 16 Nov 2000 17:20:52 +0000 Subject: Major update. Almost everything has changed. - no more dynamic allocations at runtime - only once at startup - less list traversal through interpreter and key hashes - output plugins can request only certain results! --- ulogd/Makefile | 6 +- ulogd/conffile.c | 14 +- ulogd/extensions/ulogd_BASE.c | 267 ++++++++++++++++++++++----------------- ulogd/extensions/ulogd_OPRINT.c | 6 +- ulogd/extensions/ulogd_PWSNIFF.c | 42 +++--- ulogd/include/ulogd/ulogd.h | 41 +++++- ulogd/ulogd.c | 205 +++++++++++++++++++++++------- 7 files changed, 379 insertions(+), 202 deletions(-) (limited to 'ulogd') diff --git a/ulogd/Makefile b/ulogd/Makefile index 6d80dfb..2f15c62 100644 --- a/ulogd/Makefile +++ b/ulogd/Makefile @@ -3,13 +3,13 @@ LIBIPULOG=../libipulog INCIPULOG=-I../libipulog/include # Names of the plugins to be compiled -ULOGD_SL:=BASE OPRINT PWSNIFF +ULOGD_SL:=BASE OPRINT PWSNIFF #MYSQL # Normally You should not need to change anything below # CC = gcc CFLAGS = -I. -Wall $(INCIPULOG) -O2 -#CFLAGS+=-g -DDEBUG +CFLAGS+=-g -DDEBUG SH_CFLAGS:=$(CFLAGS) -fPIC @@ -27,7 +27,7 @@ conffile.o: conffile.c $(CC) $(CFLAGS) -c $< -o $@ ulogd: ulogd.c $(LIBIPULOG) ulogd.h conffile.o - $(CC) $(CFLAGS) -rdynamic -ldl -i ulogd.c conffile.o $(LIBIPULOG)/libipulog.a -o ulogd + $(CC) $(CFLAGS) -rdynamic -ldl ulogd.c -lmysqlclient conffile.o $(LIBIPULOG)/libipulog.a -o ulogd clean: rm -f ulogd *.o extensions/*.o extensions/*.so diff --git a/ulogd/conffile.c b/ulogd/conffile.c index 2489c8d..04f54f2 100644 --- a/ulogd/conffile.c +++ b/ulogd/conffile.c @@ -1,7 +1,7 @@ /* config file parser functions * (C) 2000 by Harald Welte * - * $Id: conffile.c,v 1.5 2000/09/12 14:29:36 laforge Exp $ + * $Id: conffile.c,v 1.6 2000/09/22 06:54:33 laforge Exp $ * * This code is distributed under the terms of GNU GPL */ @@ -115,7 +115,7 @@ int config_parse_file(int final) while (fgets(line, LINE_LEN, cfile)) { - DEBUGC("line read\n"); + DEBUGC("line read: %s\n", line); if (*line == '#') continue; @@ -123,18 +123,21 @@ int config_parse_file(int final) if (!word) continue; +#if 0 /* if we do the final parse and word is not a config key */ if (final && config_iskey(word)) { DEBUGC("final and key '%s' not found\n", word); err = -ERRUNKN; goto cpf_error; } +#endif args = line + strlen(word) + 1; *(args + strlen(args) - 1 ) = '\0'; - + + DEBUGC("parse_file: entering main loop\n"); for (ce = config; ce; ce = ce->next) { - DEBUGC("parse main loop\n"); + DEBUGC("parse main loop, key: %s\n", ce->key); if (strcmp(ce->key, word)) { continue; } @@ -164,12 +167,13 @@ int config_parse_file(int final) } break; } + DEBUGC("parse_file: exiting main loop\n"); } for (ce = config; ce; ce = ce->next) { DEBUGC("ce post loop, ce=%s\n", ce->key); - if ((ce->options & CONFIG_OPT_MANDATORY) && (ce->hit == 0)) { + if ((ce->options & CONFIG_OPT_MANDATORY) && (ce->hit == 0) && final) { DEBUGC("mandatory config directive %s not found\n", ce->key); config_errce = ce; diff --git a/ulogd/extensions/ulogd_BASE.c b/ulogd/extensions/ulogd_BASE.c index 391ac59..5d4ef2f 100644 --- a/ulogd/extensions/ulogd_BASE.c +++ b/ulogd/extensions/ulogd_BASE.c @@ -1,11 +1,11 @@ -/* ulogd_MAC.c, Version $Revision: 1.5 $ +/* ulogd_MAC.c, Version $Revision: 1.6 $ * * ulogd logging interpreter for MAC addresses, TIME, IP and TCP headers, etc. * * (C) 2000 by Harald Welte * This software is released under the terms of GNU GPL * - * $Id: ulogd_BASE.c,v 1.5 2000/09/22 06:54:33 laforge Exp $ + * $Id: ulogd_BASE.c,v 1.6 2000/09/26 06:25:02 laforge Exp $ * */ @@ -18,12 +18,19 @@ #include #include -ulog_iret_t *_interp_mac(ulog_packet_msg_t *pkt) +/*********************************************************************** + * Raw header + ***********************************************************************/ +static ulog_iret_t mac_rets[1] = { + { NULL, NULL, 0, ULOGD_RET_STRING, ULOGD_RETF_FREE, "raw.mac", NULL }, +}; + +ulog_iret_t *_interp_mac(struct ulog_interpreter *ip, ulog_packet_msg_t *pkt) { unsigned char *p; int i; char *buf; - ulog_iret_t *ret; + ulog_iret_t *ret = ip->result; if (pkt->mac_len) { buf = (char *) malloc(3 * pkt->mac_len + 1); @@ -32,201 +39,223 @@ ulog_iret_t *_interp_mac(ulog_packet_msg_t *pkt) p = pkt->mac; for (i = 0; i < pkt->mac_len; i++, p++) sprintf(buf, "%s%02x%c", buf, *p, i==pkt->mac_len-1 ? ' ':':'); - ret = alloc_ret(ULOGD_RET_STRING,"raw.mac.addr"); - ret->value.ptr = buf; + ret[0].value.ptr = buf; + ret[0].flags |= ULOGD_RETF_VALID; return ret; } return NULL; } -ulog_iret_t *_interp_time(ulog_packet_msg_t *pkt) -{ - ulog_iret_t *ret, *ret2; - - ret = alloc_ret(ULOGD_RET_UINT32, "oob.time.sec"); - ret2 = alloc_ret(ULOGD_RET_UINT32, "oob.time.usec"); - - ret->value.ui32 = pkt->timestamp_sec; - ret->next = ret2; +/*********************************************************************** + * OUT OF BAND + ***********************************************************************/ - ret2->value.ui32 = pkt->timestamp_usec; - - return ret; -} +static ulog_iret_t oob_rets[] = { + { NULL, NULL, 0, ULOGD_RET_STRING, ULOGD_RETF_NONE, "oob.prefix", NULL }, + { NULL, NULL, 0, ULOGD_RET_UINT32, ULOGD_RETF_NONE, "oob.time.sec", NULL }, + { NULL, NULL, 0, ULOGD_RET_UINT32, ULOGD_RETF_NONE, "oob.time.usec", NULL }, + { NULL, NULL, 0, ULOGD_RET_UINT32, ULOGD_RETF_NONE, "oob.mark", NULL }, +}; -ulog_iret_t *_interp_prefix(ulog_packet_msg_t *pkt) +ulog_iret_t *_interp_oob(struct ulog_interpreter *ip, ulog_packet_msg_t *pkt) { - ulog_iret_t *ret; - - ret = alloc_ret(ULOGD_RET_STRING, "oob.prefix"); - ret->value.ptr = malloc(sizeof(pkt->prefix)); - strcpy(ret->value.ptr, pkt->prefix); + ulog_iret_t *ret = ip->result; + + ret[0].value.ptr = pkt->prefix; + ret[0].flags |= ULOGD_RETF_VALID; + ret[1].value.ui32 = pkt->timestamp_sec; + ret[1].flags |= ULOGD_RETF_VALID; + ret[2].value.ui32 = pkt->timestamp_usec; + ret[2].flags |= ULOGD_RETF_VALID; + ret[3].value.ui32 = pkt->mark; + ret[3].flags |= ULOGD_RETF_VALID; return ret; } -ulog_iret_t *_interp_mark(ulog_packet_msg_t *pkt) -{ - ulog_iret_t *ret; - - ret = alloc_ret(ULOGD_RET_UINT32, "oob.mark"); - ret->value.ui32 = pkt->mark; - - return ret; -} +/*********************************************************************** + * IP HEADER + ***********************************************************************/ + +static ulog_iret_t iphdr_rets[] = { + { NULL, NULL, 0, ULOGD_RET_IPADDR, ULOGD_RETF_NONE, "ip.saddr", 0 }, + { NULL, NULL, 0, ULOGD_RET_IPADDR, ULOGD_RETF_NONE, "ip.daddr", 0 }, + { NULL, NULL, 0, ULOGD_RET_UINT8, ULOGD_RETF_NONE, "ip.protocol", 0 }, + { NULL, NULL, 0, ULOGD_RET_UINT8, ULOGD_RETF_NONE, "ip.tos", 0 }, + { NULL, NULL, 0, ULOGD_RET_UINT8, ULOGD_RETF_NONE, "ip.ttl", 0 }, + { NULL, NULL, 0, ULOGD_RET_UINT16, ULOGD_RETF_NONE, "ip.totlen", 0 }, + { NULL, NULL, 0, ULOGD_RET_UINT8, ULOGD_RETF_NONE, "ip.ihl", 0 }, + { NULL, NULL, 0, ULOGD_RET_UINT16, ULOGD_RETF_NONE, "ip.csum", 0 }, +}; -ulog_iret_t *_interp_iphdr(ulog_packet_msg_t *pkt) +ulog_iret_t *_interp_iphdr(struct ulog_interpreter *ip, ulog_packet_msg_t *pkt) { - ulog_iret_t *ret, *ret2; + ulog_iret_t *ret = ip->result; struct iphdr *iph = (struct iphdr *) pkt->payload; - ret = alloc_ret(ULOGD_RET_IPADDR, "ip.hdr.saddr"); - ret->value.ui32 = ntohl(iph->saddr); - - ret->next = ret2 = alloc_ret(ULOGD_RET_IPADDR, "ip.hdr.daddr"); - ret2->value.ui32 = ntohl(iph->daddr); - - ret2 = ret2->next = alloc_ret(ULOGD_RET_UINT8, "ip.hdr.protocol"); - ret2->value.ui8 = iph->protocol; - - ret2 = ret2->next = alloc_ret(ULOGD_RET_UINT8, "ip.hdr.tos"); - ret2->value.ui8 = ntohs(iph->tos); - - ret2 = ret2->next = alloc_ret(ULOGD_RET_UINT8, "ip.hdr.ttl"); - ret2->value.ui8 = iph->ttl; - - ret2 = ret2->next = alloc_ret(ULOGD_RET_UINT16, "ip.hdr.tot_len"); - ret2->value.ui16 = ntohs(iph->tot_len); - - ret2 = ret2->next = alloc_ret(ULOGD_RET_UINT8, "ip.hdr.ihl"); - ret2->value.ui8 = iph->ihl; - - ret2 = ret2->next = alloc_ret(ULOGD_RET_UINT16, "ip.hdr.csum"); - ret2->value.ui16 = ntohs(iph->check); + ret[0].value.ui32 = ntohl(iph->saddr); + ret[0].flags |= ULOGD_RETF_VALID; + ret[1].value.ui32 = ntohl(iph->daddr); + ret[1].flags |= ULOGD_RETF_VALID; + ret[2].value.ui8 = iph->protocol; + ret[2].flags |= ULOGD_RETF_VALID; + ret[3].value.ui8 = ntohs(iph->tos); + ret[3].flags |= ULOGD_RETF_VALID; + ret[4].value.ui8 = iph->ttl; + ret[4].flags |= ULOGD_RETF_VALID; + ret[5].value.ui16 = ntohs(iph->tot_len); + ret[5].flags |= ULOGD_RETF_VALID; + ret[6].value.ui8 = iph->ihl; + ret[6].flags |= ULOGD_RETF_VALID; + ret[7].value.ui16 = ntohs(iph->check); + ret[7].flags |= ULOGD_RETF_VALID; return ret; } -ulog_iret_t *_interp_tcphdr(ulog_packet_msg_t *pkt) +/*********************************************************************** + * TCP HEADER + ***********************************************************************/ +static ulog_iret_t tcphdr_rets[] = { + { NULL, NULL, 0, ULOGD_RET_UINT16, ULOGD_RETF_NONE, "tcp.sport", 0 }, + { NULL, NULL, 0, ULOGD_RET_UINT16, ULOGD_RETF_NONE, "tcp.dport", 0 }, + { NULL, NULL, 0, ULOGD_RET_UINT32, ULOGD_RETF_NONE, "tcp.seq", 0 }, + { NULL, NULL, 0, ULOGD_RET_UINT32, ULOGD_RETF_NONE, "tcp.ackseq", 0 }, + { NULL, NULL, 0, ULOGD_RET_UINT16, ULOGD_RETF_NONE, "tcp.window", 0 }, + { NULL, NULL, 0, ULOGD_RET_BOOL, ULOGD_RETF_NONE, "tcp.urg", 0 }, + { NULL, NULL, 0, ULOGD_RET_UINT16, ULOGD_RETF_NONE, "tcp.urgp", 0 }, + { NULL, NULL, 0, ULOGD_RET_BOOL, ULOGD_RETF_NONE, "tcp.ack", 0 }, + { NULL, NULL, 0, ULOGD_RET_BOOL, ULOGD_RETF_NONE, "tcp.psh", 0 }, + { NULL, NULL, 0, ULOGD_RET_BOOL, ULOGD_RETF_NONE, "tcp.rst", 0 }, + { NULL, NULL, 0, ULOGD_RET_BOOL, ULOGD_RETF_NONE, "tcp.syn", 0 }, + { NULL, NULL, 0, ULOGD_RET_BOOL, ULOGD_RETF_NONE, "tcp.fin", 0 }, +}; + +ulog_iret_t *_interp_tcphdr(struct ulog_interpreter *ip, ulog_packet_msg_t *pkt) { struct iphdr *iph = (struct iphdr *) pkt->payload; void *protoh = (u_int32_t *)iph + iph->ihl; struct tcphdr *tcph = (struct tcphdr *) protoh; - ulog_iret_t *ret, *ret2; + ulog_iret_t *ret = ip->result; if (iph->protocol != IPPROTO_TCP) return NULL; - ret = alloc_ret(ULOGD_RET_UINT16, "tcp.hdr.sport"); - ret->value.ui16 = ntohs(tcph->source); - - ret->next = ret2 = alloc_ret(ULOGD_RET_UINT16, "tcp.hdr.dport"); - ret2->value.ui16 = ntohs(tcph->dest); - - ret2 = ret2->next = alloc_ret(ULOGD_RET_UINT32, "tcp.hdr.seq"); - ret2->value.ui32 = ntohl(tcph->seq); - - ret2 = ret2->next = alloc_ret(ULOGD_RET_UINT32, "tcp.hdr.ack_seq"); - ret2->value.ui32 = ntohl(tcph->ack_seq); - - ret2 = ret2->next = alloc_ret(ULOGD_RET_UINT16, "tcp.hdr.window"); - ret2->value.ui16 = ntohs(tcph->window); - + ret[0].value.ui16 = ntohs(tcph->source); + ret[0].flags |= ULOGD_RETF_VALID; + ret[1].value.ui16 = ntohs(tcph->dest); + ret[1].flags |= ULOGD_RETF_VALID; + ret[2].value.ui32 = ntohl(tcph->seq); + ret[2].flags |= ULOGD_RETF_VALID; + ret[3].value.ui32 = ntohl(tcph->ack_seq); + ret[3].flags |= ULOGD_RETF_VALID; + ret[4].value.ui16 = ntohs(tcph->window); + ret[4].flags |= ULOGD_RETF_VALID; if (tcph->urg) { - ret2 = ret2->next = alloc_ret(ULOGD_RET_BOOL, "tcp.hdr.urg"); - ret2->value.b = 1; - - ret2 = ret2->next = alloc_ret(ULOGD_RET_UINT16, "tcp.hdr.urgp"); - ret2->value.ui16 = ntohs(tcph->urg_ptr); + ret[5].value.b = tcph->urg; + ret[5].flags |= ULOGD_RETF_VALID; + ret[6].value.ui16 = ntohs(tcph->urg_ptr); + ret[6].flags |= ULOGD_RETF_VALID; } if (tcph->ack) { - ret2 = ret2->next = alloc_ret(ULOGD_RET_BOOL, "tcp.hdr.ack"); - ret2->value.b = 1; + ret[7].value.b = tcph->ack; + ret[7].flags |= ULOGD_RETF_VALID; } if (tcph->psh) { - ret2 = ret2->next = alloc_ret(ULOGD_RET_BOOL, "tcp.hdr.psh"); - ret2->value.b = 1; + ret[8].value.b = tcph->psh; + ret[8].flags |= ULOGD_RETF_VALID; } if (tcph->rst) { - ret2 = ret2->next = alloc_ret(ULOGD_RET_BOOL, "tcp.hdr.rst"); - ret2->value.b = 1; + ret[9].value.b = tcph->rst; + ret[9].flags |= ULOGD_RETF_VALID; } if (tcph->syn) { - ret2 = ret2->next = alloc_ret(ULOGD_RET_BOOL, "tcp.hdr.syn"); - ret2->value.b = 1; + ret[10].value.b = tcph->syn; + ret[10].flags |= ULOGD_RETF_VALID; } if (tcph->fin) { - ret2 = ret2->next = alloc_ret(ULOGD_RET_BOOL, "tcp.hdr.fin"); - ret2->value.b = 1; + ret[11].value.b = tcph->fin; + ret[11].flags |= ULOGD_RETF_VALID; } return ret; } -ulog_iret_t *_interp_udp(ulog_packet_msg_t *pkt) +/*********************************************************************** + * UDP HEADER + ***********************************************************************/ +static ulog_iret_t udphdr_rets[] = { + { NULL, NULL, 0, ULOGD_RET_UINT16, ULOGD_RETF_NONE, "udp.sport", 0 }, + { NULL, NULL, 0, ULOGD_RET_UINT16, ULOGD_RETF_NONE, "udp.dport", 0 }, + { NULL, NULL, 0, ULOGD_RET_UINT16, ULOGD_RETF_NONE, "upd.len", 0 }, +}; +ulog_iret_t *_interp_udp(struct ulog_interpreter *ip, ulog_packet_msg_t *pkt) { struct iphdr *iph = (struct iphdr *) pkt->payload; void *protoh = (u_int32_t *)iph + iph->ihl; struct udphdr *udph = protoh; - ulog_iret_t *ret, *ret2; + ulog_iret_t *ret = ip->result; if (iph->protocol != IPPROTO_UDP) return NULL; - ret = alloc_ret(ULOGD_RET_UINT16, "udp.hdr.sport"); - ret->value.ui16 = ntohs(udph->source); - - ret2 = ret->next = alloc_ret(ULOGD_RET_UINT16, "udp.hdr.dport"); - ret2->value.ui16 = ntohs(udph->dest); - - ret2 = ret2->next = alloc_ret(ULOGD_RET_UINT16, "udp.hdr.len"); - ret2->value.ui16 = ntohs(udph->len); + ret[0].value.ui16 = ntohs(udph->source); + ret[0].flags |= ULOGD_RETF_VALID; + ret[1].value.ui16 = ntohs(udph->dest); + ret[1].flags |= ULOGD_RETF_VALID; + ret[2].value.ui16 = ntohs(udph->len); + ret[2].flags |= ULOGD_RETF_VALID; return ret; } -ulog_iret_t *_interp_icmp(ulog_packet_msg_t *pkt) +/*********************************************************************** + * ICMP HEADER + ***********************************************************************/ + +static ulog_iret_t icmphdr_rets[] = { + { NULL, NULL, 0, ULOGD_RET_UINT16, ULOGD_RETF_NONE, "icmp.type", 0 }, +}; + +ulog_iret_t *_interp_icmp(struct ulog_interpreter *ip, ulog_packet_msg_t *pkt) { struct iphdr *iph = (struct iphdr *) pkt->payload; void *protoh = (u_int32_t *) (iph + iph->ihl); struct icmphdr *icmph = protoh; - ulog_iret_t *ret; + ulog_iret_t *ret = ip->result; if (iph->protocol != IPPROTO_ICMP) return NULL; - ret = alloc_ret(ULOGD_RET_UINT8, "icmp.hdr.type"); - ret->value.ui8 = icmph->type; + ret[0].value.ui8 = icmph->type; + ret[0].flags |= ULOGD_RETF_VALID; return ret; } - -static ulog_interpreter_t base_ip[] = { - - { NULL, "raw.mac", &_interp_mac }, - { NULL, "oob.time", &_interp_time }, - { NULL, "oob.prefix", &_interp_prefix }, - { NULL, "oob.mark", &_interp_mark }, - { NULL, "ip.hdr", &_interp_iphdr }, - { NULL, "tcp.hdr", &_interp_tcphdr }, - { NULL, "icmp.hdr", &_interp_icmp }, - { NULL, "udp.hdr", &_interp_udp }, - { NULL, "", NULL }, +static ulog_interpreter_t base_ip[] = { + { NULL, "raw", 0, &_interp_mac, 1, &mac_rets }, + { NULL, "oob", 0, &_interp_oob, 4, &oob_rets }, + { NULL, "ip", 0, &_interp_iphdr, 8, &iphdr_rets }, + { NULL, "tcp", 0, &_interp_tcphdr, 12, &tcphdr_rets }, + { NULL, "icmp", 0, &_interp_icmp, 1, &icmphdr_rets }, + { NULL, "udp", 0, &_interp_udp, 3, &udphdr_rets }, + { NULL, "", 0, NULL, 0, { NULL } }, }; + void _base_reg_ip(void) { ulog_interpreter_t *ip = base_ip; ulog_interpreter_t *p; - for (p = ip; p->interp; p++) + for (p = ip; p->interp; p++) { register_interpreter(p); + } } - void _init(void) { _base_reg_ip(); diff --git a/ulogd/extensions/ulogd_OPRINT.c b/ulogd/extensions/ulogd_OPRINT.c index 0b551b6..3fa42ed 100644 --- a/ulogd/extensions/ulogd_OPRINT.c +++ b/ulogd/extensions/ulogd_OPRINT.c @@ -1,11 +1,11 @@ -/* ulogd_MAC.c, Version $Revision: 1.3 $ +/* ulogd_MAC.c, Version $Revision: 1.4 $ * * ulogd output target for logging to a file * * (C) 2000 by Harald Welte * This software is released under the terms of GNU GPL * - * $Id: ulogd_OPRINT.c,v 1.3 2000/09/12 14:29:37 laforge Exp $ + * $Id: ulogd_OPRINT.c,v 1.4 2000/09/22 06:54:33 laforge Exp $ * */ @@ -34,7 +34,7 @@ int _output_print(ulog_iret_t *res) ulog_iret_t *ret; fprintf(of, "===>PACKET BOUNDARY\n"); - for (ret = res; ret; ret = ret->next) { + for (ret = res; ret; ret = ret->cur_next) { fprintf(of,"%s=", ret->key); switch (ret->type) { case ULOGD_RET_STRING: diff --git a/ulogd/extensions/ulogd_PWSNIFF.c b/ulogd/extensions/ulogd_PWSNIFF.c index f8e1327..cc0f19e 100644 --- a/ulogd/extensions/ulogd_PWSNIFF.c +++ b/ulogd/extensions/ulogd_PWSNIFF.c @@ -1,11 +1,11 @@ -/* ulogd_PWSNIFF.c, Version $Revision: 1.1 $ +/* ulogd_PWSNIFF.c, Version $Revision: 1.2 $ * * ulogd logging interpreter for POP3 / FTP like plaintext passwords. * * (C) 2000 by Harald Welte * This software is released under the terms of GNU GPL * - * $Id: ulogd_PWSNIFF.c,v 1.1 2000/08/17 08:03:22 laforge Exp $ + * $Id: ulogd_PWSNIFF.c,v 1.2 2000/09/22 06:54:33 laforge Exp $ * */ @@ -46,15 +46,14 @@ static char *_get_next_blank(char* begp, char *endp) return NULL; } -static ulog_iret_t *_interp_pwsniff(ulog_packet_msg_t *pkt) +static ulog_iret_t *_interp_pwsniff(ulog_interpreter_t *ip, ulog_packet_msg_t *pkt) { struct iphdr *iph = (struct iphdr *) pkt->payload; void *protoh = (u_int32_t *)iph + iph->ihl; struct tcphdr *tcph = protoh; u_int32_t tcplen = ntohs(iph->tot_len) - iph->ihl * 4; unsigned char *ptr, *begp, *pw_begp, *endp, *pw_endp; - ulog_iret_t *ret = NULL; - ulog_iret_t *ret2; + ulog_iret_t *ret = ip->result; int len, pw_len, i, cont = 0; len = pw_len = 0; @@ -94,37 +93,36 @@ static ulog_iret_t *_interp_pwsniff(ulog_packet_msg_t *pkt) } if (len) { - ret = alloc_ret(ULOGD_RET_STRING, "pwsniff.user"); - ret->value.ptr = (char *) malloc(len+1); - if (!ret->value.ptr) { + ret[0].value.ptr = (char *) malloc(len+1); + ret[0].flags |= ULOGD_RETF_VALID; + if (!ret[0].value.ptr) { ulogd_error("_interp_pwsniff: OOM (size=%u)\n", len); - free(ret); return NULL; } - strncpy(ret->value.ptr, begp, len); - *((char *)ret->value.ptr + len + 1) = '\0'; + strncpy(ret[0].value.ptr, begp, len); + *((char *)ret[0].value.ptr + len + 1) = '\0'; } if (pw_len) { - ret2 = alloc_ret(ULOGD_RET_STRING,"pwsniff.pass"); - ret2->value.ptr = (char *) malloc(pw_len+1); - if (!ret2->value.ptr){ + ret[1].value.ptr = (char *) malloc(pw_len+1); + ret[1].flags |= ULOGD_RETF_VALID; + if (!ret[1].value.ptr){ ulogd_error("_interp_pwsniff: OOM (size=%u)\n", pw_len); - free(ret2); return NULL; } - strncpy(ret2->value.ptr, pw_begp, pw_len); - *((char *)ret2->value.ptr + pw_len + 1) = '\0'; + strncpy(ret[1].value.ptr, pw_begp, pw_len); + *((char *)ret[1].value.ptr + pw_len + 1) = '\0'; - if (ret) - ret->next = ret2; - else - ret = ret2; } return ret; } + +static ulog_iret_t pwsniff_rets[] = { + { NULL, NULL, 0, ULOGD_RET_STRING, ULOGD_RETF_FREE, "pwsniff.user", 0 }, + { NULL, NULL, 0, ULOGD_RET_STRING, ULOGD_RETF_FREE, "pwsniff.pass", 0 }, +}; static ulog_interpreter_t base_ip[] = { - { NULL, "pwsniff", &_interp_pwsniff }, + { NULL, "pwsniff", 0, &_interp_pwsniff, 2, &pwsniff_rets }, { NULL, "", NULL }, }; void _base_reg_ip(void) diff --git a/ulogd/include/ulogd/ulogd.h b/ulogd/include/ulogd/ulogd.h index 24986b0..883cf10 100644 --- a/ulogd/include/ulogd/ulogd.h +++ b/ulogd/include/ulogd/ulogd.h @@ -1,6 +1,6 @@ #ifndef _ULOGD_H #define _ULOGD_H -/* ulogd, Version $Revision: 1.6 $ +/* ulogd, Version $Revision: 1.7 $ * * first try of a logging daemon for my netfilter ULOG target * for the linux 2.4 netfilter subsystem. @@ -9,10 +9,11 @@ * * this code is released under the terms of GNU GPL * - * $Id: ulogd.h,v 1.6 2000/09/12 13:43:34 laforge Exp $ + * $Id: ulogd.h,v 1.7 2000/09/12 14:29:37 laforge Exp $ */ #include +#include /* All types with MSB = 1 make use of value.ptr * other types use one of the union's member */ @@ -34,11 +35,16 @@ #define ULOGD_RET_IPADDR 0x0100 -/* types with lenght field*/ +/* types with length field */ #define ULOGD_RET_STRING 0x8020 #define ULODG_RET_RAW 0x8030 -#define ULOGD_RET_OTHER 0xffff + +/* FLAGS */ +#define ULOGD_RETF_NONE 0x0000 +#define ULOGD_RETF_VALID 0x0001 +#define ULOGD_RETF_FREE 0x0002 + /* maximum length of ulogd key */ #define ULOGD_MAX_KEYLEN 32 @@ -51,10 +57,19 @@ extern FILE *logfile; typedef struct ulog_iret { + /* next interpreter return (key) in the global list */ struct ulog_iret *next; + /* next interpreter in linked list for current result */ + struct ulog_iret *cur_next; + /* length of the returned value (only for lengthed types */ u_int32_t len; + /* type of the returned value (ULOGD_IRET_...) */ u_int16_t type; + /* flags (i.e. free, ...) */ + u_int16_t flags; + /* name of this key */ char key[ULOGD_MAX_KEYLEN]; + /* and finally the returned value */ union { u_int8_t b; u_int8_t ui8; @@ -70,14 +85,27 @@ typedef struct ulog_iret { } ulog_iret_t; typedef struct ulog_interpreter { + /* next interpreter in old-style linked list */ struct ulog_interpreter *next; + /* name of this interpreter (predefined by plugin) */ char name[ULOGD_MAX_KEYLEN]; - ulog_iret_t* (*interp)(ulog_packet_msg_t *pkt); + /* ID for this interpreter (dynamically assigned) */ + unsigned int id; + /* function to call for each packet */ + ulog_iret_t* (*interp)(struct ulog_interpreter *ip, + ulog_packet_msg_t *pkt); + /* number of keys this interpreter has */ + unsigned int key_num; + /* keys of this particular interpreter */ + ulog_iret_t *result; } ulog_interpreter_t; typedef struct ulog_output { + /* next output in the linked list */ struct ulog_output *next; + /* name of this ouput plugin */ char name[ULOGD_MAX_KEYLEN]; + /* callback function */ int* (*output)(ulog_iret_t *ret); } ulog_output_t; @@ -100,4 +128,7 @@ void ulogd_log(int level, const char *message, ...); /* backwards compatibility */ #define ulogd_error(format, args...) ulogd_log(ULOGD_ERROR, format, ## args) +/* get an interpreter hash id by name */ +unsigned int interh_getid(const char *name); + #endif diff --git a/ulogd/ulogd.c b/ulogd/ulogd.c index a91be2c..883c91e 100644 --- a/ulogd/ulogd.c +++ b/ulogd/ulogd.c @@ -1,4 +1,4 @@ -/* ulogd, Version $Revision: 1.9 $ +/* ulogd, Version $Revision: 1.10 $ * * first try of a logging daemon for my netfilter ULOG target * for the linux 2.4 netfilter subsystem. @@ -7,7 +7,7 @@ * * this code is released under the terms of GNU GPL * - * $Id: ulogd.c,v 1.9 2000/09/12 13:43:34 laforge Exp $ + * $Id: ulogd.c,v 1.10 2000/09/12 14:29:37 laforge Exp $ */ #include @@ -48,36 +48,147 @@ FILE *logfile = NULL; - /* linked list for all registered interpreters */ static ulog_interpreter_t *ulogd_interpreters; /* linked list for all registered output targets */ static ulog_output_t *ulogd_outputs; +/*********************************************************************** + * INTERPRETER AND KEY HASH FUNCTIONS + ***********************************************************************/ + +/* hashtable for all registered interpreters */ +static ulog_interpreter_t *ulogd_interh[100]; +static unsigned int ulogd_interh_ids; + +/* allocate a new interpreter id and write it into the interpreter struct */ +static unsigned int interh_allocid(ulog_interpreter_t *ip) +{ + unsigned int id; + + id = ++ulogd_interh_ids; + ip->id = id; + ulogd_interh[id] = ip; + return id; +} + +/* get interpreter d by name */ +unsigned int interh_getid(const char *name) +{ + int i; + for (i = 1; i <= ulogd_interh_ids; i++) + if (!strcmp(name, (ulogd_interh[i])->name)) + return i; + + return 0; +} + +/* dump out the contents of the interpreter hash */ +static void interh_dump(void) +{ + int i; + + for (i = 1; i <= ulogd_interh_ids; i++) + printf("ulogd_interh[%d] = %s\n", i, (ulogd_interh[i])->name); + +} + +struct ulogd_keyh_entry { + ulog_interpreter_t *interp; /* interpreter for this key */ + unsigned int offset; /* offset within interpreter */ + const char *name; /* name of this particular key */ +}; + +static struct ulogd_keyh_entry ulogd_keyh[100]; +static unsigned int ulogd_keyh_ids; + +/* allocate a new key_id */ +static unsigned int keyh_allocid(ulog_interpreter_t *ip, unsigned int offset, + const char *name) +{ + unsigned int id; + + id = ++ulogd_keyh_ids; + + ulogd_keyh[id].interp = ip; + ulogd_keyh[id].offset = offset; + ulogd_keyh[id].name = name; + + return id; +} + +static void keyh_dump(void) +{ + int i; + + printf("dumping keyh\n"); + for (i = 1; i <= ulogd_keyh_ids; i++) + printf("ulogd_keyh[%d] = %s:%d\n", i, ulogd_keyh[i].interp->name, + ulogd_keyh[i].offset); + +} + +/* get keyid by name */ +unsigned int keyh_getid(const char *name) +{ + int i; + for (i = 1; i <= ulogd_keyh_ids; i++) + if (!strcmp(name, ulogd_keyh[i].name)) + return i; + + return 0; +} + +/* get key name by keyid */ +inline char *keyh_getname(unsigned int id) +{ + return ulogd_keyh[id].interp->name; +} + + /* try to lookup a registered interpreter for a given name */ static ulog_interpreter_t *find_interpreter(const char *name) { - ulog_interpreter_t *ptr; - - for (ptr = ulogd_interpreters; ptr; ptr = ptr->next) { - if (strcmp(name, ptr->name) == 0) - return ptr; - } + int id; + + id = interh_getid(name); + if (!id) + return NULL; - return NULL; + return ulogd_interh[id]; } /* the function called by all interpreter plugins for registering their * target. */ void register_interpreter(ulog_interpreter_t *me) { + int i; + + /* check if we already have an interpreter with this name */ if (find_interpreter(me->name)) { ulogd_error("interpreter `%s' already registered\n", me->name); exit(1); } + ulogd_log(ULOGD_NOTICE, "registering interpreter `%s'\n", me->name); + + /* allocate a new interpreter id for it */ + interh_allocid(me); + + /* - allocate one keyh_id for each result of this interpreter + * - link the elements to each other */ + for (i = 0; i < me->key_num; i++) { + keyh_allocid(me, i, me->result[i].key); + if (i != me->key_num - 1) + me->result[i].next = &me->result[i+1]; + } + + if (ulogd_interpreters) + me->result[me->key_num - 1].next = &ulogd_interpreters->result[0]; + + /* all work done, we can prepend the new interpreter to the list */ me->next = ulogd_interpreters; ulogd_interpreters = me; } @@ -121,25 +232,7 @@ ulog_iret_t *alloc_ret(const u_int16_t type, const char* key) return ptr; } -/* free a ulog_iret_t* including all linked ones and the value pointers */ -void free_ret(ulog_iret_t *ret) -{ - ulog_iret_t *ptr = NULL; - ulog_iret_t *nextptr = NULL; - - for (ptr = ret; ptr; ptr = nextptr) { - if ((ptr->type | 0x7fff) == 0xffff) { - free(ptr->value.ptr); - } - if (ptr->next) { - nextptr = ptr->next; - } else { - nextptr = NULL; - } - free(ptr); - } -} - +/* log message to the logfile */ void ulogd_log(int level, const char *format, ...) { char *timestr; @@ -156,6 +249,7 @@ void ulogd_log(int level, const char *format, ...) tm = time(NULL); timestr = ctime(&tm); + timestr[strlen(timestr)-1] = '\0'; fprintf(outfd, "%s <%1.1d>", timestr, level); vfprintf(outfd, format, ap); @@ -172,28 +266,46 @@ static void propagate_results(ulog_iret_t *ret) } } +/* clean results (set all values to 0 and free pointers) */ +static void clean_results(ulog_iret_t *ret) +{ + ulog_iret_t *r; + + for (r = ret; r; r = r->next) { + if (r->flags & ULOGD_RETF_FREE) + free(r->value.ptr); + memset(&r->value, 0, sizeof(r->value)); + r->flags &= ~ULOGD_RETF_VALID; + } +} + +#define IS_VALID(x) (x.flags & ULOGD_RETF_VALID) + /* call all registered interpreters and hand the results over to * propagate_results */ static void handle_packet(ulog_packet_msg_t *pkt) { - ulog_interpreter_t *ptr; - ulog_iret_t *ret, *b; + ulog_iret_t *ret; ulog_iret_t *allret = NULL; - - /* call each registered interpreter */ - for (ptr = ulogd_interpreters; ptr; ptr = ptr->next) { - ret = (*ptr->interp)(pkt); - if (ret) { - /* prepend the results to allret */ - if (allret) { - for (b = ret; b->next; b = b->next); - b->next = allret; + ulog_interpreter_t *ip; + + unsigned int i,j; + + for (i = 1; i <= ulogd_interh_ids; i++) { + ip = ulogd_interh[i]; + /* call interpreter */ + if (ret = ((ip)->interp)(ip, pkt)) { + /* create references for result linked-list */ + for (j = 0; j < ip->key_num; j++) { + if (IS_VALID(ip->result[j])) { + ip->result[j].cur_next = allret; + allret = &ip->result[j]; + } } - allret = ret; } - } + } propagate_results(allret); - free_ret(allret); + clean_results(ulogd_interpreters->result); } /* silly plugin loader to dlopen() all available plugins */ @@ -212,13 +324,16 @@ static void load_plugins(char *dir) DEBUGP("load_plugins: %s\n", dent->d_name); sprintf(fname, "%s/%s", dir, dent->d_name); if (!dlopen(fname, RTLD_NOW)) - ulogd_error("load_plugins: %s", dlerror()); + ulogd_error("load_plugins: %s\n", dlerror()); } } free(fname); } else ulogd_error("No plugin directory: %s\n", dir); + interh_dump(); + keyh_dump(); + } static int logfile_open(const char *name) @@ -253,7 +368,7 @@ static int parse_conffile(int final) ulogd_error("ERROR: option occurred more than once\n"); break; case -ERRUNKN: - ulogd_error("ERROR: unknown config key, %s\n", + ulogd_error("ERROR: unknown config key\n"); config_errce->key); break; } -- cgit v1.2.3