From b7e75a6deea1ecd0cfe306815f83985b4f39e38b Mon Sep 17 00:00:00 2001 From: laforge Date: Wed, 2 Aug 2000 08:41:55 +0000 Subject: Initial revision --- ulogd/extensions/ulogd_BASE.c | 216 ++++++++++++++++++++++++++++++++++++++++++ ulogd/include/ulogd/ulogd.h | 55 +++++++++++ ulogd/ulogd.c | 204 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 475 insertions(+) create mode 100644 ulogd/extensions/ulogd_BASE.c create mode 100644 ulogd/include/ulogd/ulogd.h create mode 100644 ulogd/ulogd.c (limited to 'ulogd') diff --git a/ulogd/extensions/ulogd_BASE.c b/ulogd/extensions/ulogd_BASE.c new file mode 100644 index 0000000..6c9876e --- /dev/null +++ b/ulogd/extensions/ulogd_BASE.c @@ -0,0 +1,216 @@ +/* ulogd_MAC.c, Version $Revision$ + * + * ulogd logging interpreter for MAC addresses, TIME, etc. + * + * (C) 2000 by Harald Welte + * This software is released under the terms of GNU GPL + * + * $Id$ + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#define NIPQUAD(addr) \ + ((unsigned char *)&addr)[0], \ + ((unsigned char *)&addr)[1], \ + ((unsigned char *)&addr)[2], \ + ((unsigned char *)&addr)[3] + + +ulog_iret_t *_interp_mac(ulog_packet_msg_t *pkt) +{ + unsigned char *p; + int i; + char *buf; + ulog_iret_t *ret; + + if (pkt->mac_len) + { + buf = (char *) malloc(3 * pkt->mac_len + 1); + *buf = 0; + + 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 = buf; + return ret; + + } + return NULL; +} + +ulog_iret_t *_interp_time(ulog_packet_msg_t *pkt) +{ + ulog_iret_t *ret, *ret2; + unsigned long *ptr; + + ret = alloc_ret(ULOGD_RET_UINT64, "oob.time.sec"); + ret2 = alloc_ret(ULOGD_RET_UINT64, "oob.time.usec"); + + ptr = (unsigned long *) malloc(sizeof(unsigned long)); + *ptr = pkt->timestamp_sec; + ret->value = ptr; + ret->next = ret2; + + ptr = (unsigned long *) malloc (sizeof(unsigned long)); + *ptr = pkt->timestamp_usec; + ret2->value = ptr; + + return ret; +} + +ulog_iret_t *_interp_prefix(ulog_packet_msg_t *pkt) +{ + ulog_iret_t *ret; + + ret = alloc_ret(ULOGD_RET_STRING, "oob.prefix"); + ret->value = malloc(sizeof(pkt->prefix)); + strcpy(ret->value, pkt->prefix); + + return ret; +} + +ulog_iret_t *_interp_mark(ulog_packet_msg_t *pkt) +{ + ulog_iret_t *ret; + u_int32_t *mk; + + ret = alloc_ret(ULOGD_RET_UINT32, "oob.mark"); + mk = (u_int32_t *) malloc(sizeof(u_int32_t)); + *mk = pkt->mark; + ret->value = mk; + + return ret; +} + +ulog_iret_t *_interp_iphdr(ulog_packet_msg_t *pkt) +{ + ulog_iret_t *ret, *ret2; + struct iphdr *iph = (struct iphdr *) pkt->payload; + u_int32_t *ip; + u_int8_t *ui8; + u_int16_t *ui16; + + ret = alloc_ret(ULOGD_RET_IPADDR, "ip.hdr.saddr"); + ip = malloc(sizeof(u_int32_t)); + *ip = iph->saddr; + ret->value = ip; + + ret->next = ret2 = alloc_ret(ULOGD_RET_IPADDR, "ip.hdr.daddr"); + ip = malloc(sizeof(u_int32_t)); + *ip = iph->daddr; + ret2->value = ip; + + ret2 = ret2->next = alloc_ret(ULOGD_RET_UINT8, "ip.hdr.protocol"); + ui8 = malloc(sizeof(u_int8_t)); + *ui8 = iph->protocol; + ret2->value = ui8; + + ret2 = ret2->next = alloc_ret(ULOGD_RET_UINT8, "ip.hdr.tos"); + ui8 = malloc(sizeof(u_int8_t)); + *ui8 = ntohs(iph->tos); + ret2->value = ui8; + + ret2 = ret2->next = alloc_ret(ULOGD_RET_UINT8, "ip.hdr.ttl"); + ui8 = malloc(sizeof(u_int8_t)); + *ui8 = iph->ttl; + ret2->value = ui8; + + ret2 = ret2->next = alloc_ret(ULOGD_RET_UINT16, "ip.hdr.tot_len"); + ui16 = malloc(sizeof(u_int16_t)); + *ui16 = ntohs(iph->tot_len); + ret2->value = ui16; + + ret2 = ret2->next = alloc_ret(ULOGD_RET_UINT8, "ip.hdr.ihl"); + ui8 = malloc(sizeof(u_int8_t)); + *ui8 = iph->ihl; + ret2->value = ui8; + + return ret; +} + +ulog_iret_t *_interp_tcphdr(ulog_packet_msg_t *pkt) +{ + struct iphdr *iph = (struct iphdr *) pkt->payload; + struct tcphdr *tcph = (struct tcphdr *) (iph + iph->ihl); + ulog_iret_t *ret, *ret2; + u_int16_t *ui16; + u_int32_t *ui32; + + if (iph->protocol != IPPROTO_TCP) + return NULL; + + ret = alloc_ret(ULOGD_RET_UINT16, "tcp.hdr.sport"); + ui16 = malloc(sizeof(u_int16_t)); + *ui16 = ntohs(tcph->source); + ret->value = ui16; + + ret->next = ret2 = alloc_ret(ULOGD_RET_UINT16, "tcp.hdr.sport"); + ui16 = malloc(sizeof(u_int16_t)); + *ui16 = ntohs(tcph->dest); + ret2->value = ui16; + + ret2 = ret2->next = alloc_ret(ULOGD_RET_UINT32, "tcp.hdr.seq"); + ui32 = malloc(sizeof(u_int32_t)); + *ui32 = ntohl(tcph->seq); + ret2->value = ui32; + + ret2 = ret2->next = alloc_ret(ULOGD_RET_UINT32, "tcp.hdr.ack_seq"); + ui32 = malloc(sizeof(u_int32_t)); + *ui32 = ntohl(tcph->ack_seq); + ret2->value = ui32; + + + return ret; +} + +ulog_iret_t *_interp_icmp(ulog_packet_msg_t *pkt) +{ + struct iphdr *iph = (struct iphdr *) pkt->payload; + struct icmphdr *icmph = (struct icmphdr *) (iph + iph->ihl); + ulog_iret_t *ret, *ret2; + u_int8_t *ui8; + + if (iph->protocol != IPPROTO_ICMP) + return NULL; + + ret = alloc_ret(ULOGD_RET_UINT8, "icmp.hdr.type"); + ui8 = malloc(sizeof(u_int8_t)); + *ui8 = icmph->type; + ret->value = ui8; + + 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, "", NULL }, +}; + +void _init(void) +{ + ulog_interpreter_t *ip = base_ip; + ulog_interpreter_t *p; + + for (p = ip; p->interp; p++) + { + register_interpreter(p); + } + +} diff --git a/ulogd/include/ulogd/ulogd.h b/ulogd/include/ulogd/ulogd.h new file mode 100644 index 0000000..0f3378e --- /dev/null +++ b/ulogd/include/ulogd/ulogd.h @@ -0,0 +1,55 @@ +#ifndef _ULOGD_H +#define _ULOGD_H +/* ulogd, Version $Revision: 1.1 $ + * + * first try of a logging daemon for my netfilter ULOG target + * for the linux 2.4 netfilter subsystem. + * + * (C) 2000 by Harald Welte + * + * this code is released under the terms of GNU GPL + * + * $Id: ulog_test.c,v 1.1 2000/07/30 19:34:05 laforge Exp laforge $ + */ + +#include + +/* types without length */ +#define ULOGD_RET_NONE 0x0000 + +#define ULOGD_RET_INT8 0x0001 +#define ULOGD_RET_INT16 0x0002 +#define ULOGD_RET_INT32 0x0003 +#define ULOGD_RET_INT64 0x0004 + +#define ULOGD_RET_UINT8 0x0011 +#define ULOGD_RET_UINT16 0x0012 +#define ULOGD_RET_UINT32 0x0013 +#define ULOGD_RET_UINT64 0x0014 + +#define ULOGD_RET_STRING 0x0020 + +#define ULOGD_RET_IPADDR 0x0100 + +/* types with lenght field*/ +#define ULOGD_RET_OTHER 0xffff + +#define ULOGD_MAX_KEYLEN 32 + +typedef struct ulog_iret { + struct ulog_iret *next; + u_int32_t len; + u_int16_t type; + char key[ULOGD_MAX_KEYLEN]; + void *value; +} ulog_iret_t; + +typedef struct ulog_interpreter { + struct ulog_interpreter *next; + char name[ULOGD_MAX_KEYLEN]; + ulog_iret_t* (*interp)(ulog_packet_msg_t *pkt); +} ulog_interpreter_t; + +void register_interpreter(ulog_interpreter_t *me); +ulog_iret_t *alloc_ret(const u_int16_t type, const char*); +#endif diff --git a/ulogd/ulogd.c b/ulogd/ulogd.c new file mode 100644 index 0000000..a7608f2 --- /dev/null +++ b/ulogd/ulogd.c @@ -0,0 +1,204 @@ +/* ulogd, Version $Revision: 1.1 $ + * + * first try of a logging daemon for my netfilter ULOG target + * for the linux 2.4 netfilter subsystem. + * + * (C) 2000 by Harald Welte + * + * this code is released under the terms of GNU GPL + * + * $Id: ulog_test.c,v 1.1 2000/07/30 19:34:05 laforge Exp laforge $ + */ + +#include +#include +#include +#include +#include +#include +#include "ulogd.h" + +#define MYBUFSIZ 2048 + +#define ulogd_error(format, args...) fprintf(stderr, format, ## args) +#define DEBUGP ulogd_error + +#define ULOGD_PLUGIN_DIR "/usr/local/lib/ulogd" +#define NIPQUAD(addr) \ + ((unsigned char *)&addr)[0], \ + ((unsigned char *)&addr)[1], \ + ((unsigned char *)&addr)[2], \ + ((unsigned char *)&addr)[3] + +/* linked list for all registered interpreters */ +static ulog_interpreter_t *ulogd_interpreters; + +/* try to lookup a registered interpreter for a given name */ +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) + break; + } + + return ptr; +} + +/* the function called by all interpreter plugins for registering their + * target. */ +void register_interpreter(ulog_interpreter_t *me) +{ + if (find_interpreter(me->name)) { + ulogd_error("interpreter `%s' already registered\n", + me->name); + exit(1); + } + DEBUGP("registering interpreter `%s'\n", me->name); + me->next = ulogd_interpreters; + ulogd_interpreters = me; +} + +/* allocate a new ulog_iret_t. Called by interpreter plugins */ +ulog_iret_t *alloc_ret(const u_int16_t type, const char* key) +{ + ulog_iret_t *ptr = NULL; + + ptr = (ulog_iret_t *) malloc(sizeof(ulog_iret_t)); + memset(ptr, 0, sizeof(ulog_iret_t)); + strcpy(ptr->key, key); + ptr->type = type; + + 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) { + free(ptr->value); + if (ptr->next) { + nextptr = ptr->next; + } else { + nextptr = NULL; + } + free(ptr); + } +} + +/* this should pass the result(s) to one or more registered output plugins, + * but is currently only printing them out */ +void propagate_results(ulog_iret_t *res) +{ + ulog_iret_t *ret; + + for (ret = res; ret; ret = ret->next) + { + printf("%s=", ret->key); + switch (ret->type) { + case ULOGD_RET_STRING: + printf("%s\n", ret->value); + break; + case ULOGD_RET_INT16: + case ULOGD_RET_INT32: + printf("%d\n", ret->value); + break; + case ULOGD_RET_UINT8: + printf("%u\n", *(u_int8_t *)ret->value); + break; + case ULOGD_RET_UINT16: + printf("%u\n", *(u_int16_t *)ret->value); + break; + case ULOGD_RET_UINT32: + case ULOGD_RET_UINT64: + printf("%lu\n", *(u_int32_t *)ret->value); + break; + case ULOGD_RET_IPADDR: + printf("%u.%u.%u.%u\n", + NIPQUAD(*(u_int32_t *)ret->value)); + break; + case ULOGD_RET_NONE: + printf(""); + break; + } + } +} + +/* call all registered interpreters and hand the results over to + * propagate_results */ +void handle_packet(ulog_packet_msg_t *pkt) +{ + ulog_interpreter_t *ptr; + ulog_iret_t *ret; + + for (ptr = ulogd_interpreters; ptr; ptr = ptr->next) { + ret = (*ptr->interp)(pkt); + if (ret) { + propagate_results(ret); + free_ret(ret); + } + } +} + +/* silly plugin loader to dlopen() all available plugins */ +void load_plugins(void) +{ + DIR *ldir; + struct dirent *dent; + char *fname; + + ldir = opendir(ULOGD_PLUGIN_DIR); + if (ldir) { + fname = (char *) malloc(NAME_MAX + strlen(ULOGD_PLUGIN_DIR) + + 3); + for (dent = readdir(ldir); dent; dent = readdir(ldir)) { + DEBUGP("load_plugins: %s\n", dent->d_name); + sprintf(fname, "%s/%s", ULOGD_PLUGIN_DIR, dent->d_name); + if (!dlopen(fname, RTLD_NOW)) + ulogd_error("load_plugins: %s", dlerror()); + } + free(fname); + } else + ulogd_error("no plugin directory\n"); + +} + +main(int argc, char* argv[]) +{ + struct ipulog_handle *h; + unsigned char* buf; + size_t len; + ulog_packet_msg_t *upkt; + + load_plugins(); + + /* allocate a receive buffer */ + buf = (unsigned char *) malloc(MYBUFSIZ); + + /* create ipulog handle */ + h = ipulog_create_handle(ipulog_group2gmask(32)); + if (!h) + { + /* if some error occurrs, print it to stderr */ + ipulog_perror(NULL); + exit(1); + } + + /* endless loop receiving packets and handling them over to + * handle_packet */ + while(1) + { + len = ipulog_read(h, buf, BUFSIZ, 1); + upkt = ipulog_get_packet(buf); + DEBUGP("==> packet received\n"); + handle_packet(upkt); + } + + /* just to give it a cleaner look */ + ipulog_destroy_handle(h); + +} -- cgit v1.2.3