/* most of the code was copied form the ipt_pl_LOG.c code and adapted to be
used with the ULOG package by Harald Welte (see
http://www.gnumonks.org/ftp/pub/netfilter)
Thomas Geffert <thg@users.sourceforge.net> */
#define BUILD_TARGET
#define MODULE_DATATYPE struct ipt_ulog_info
#define MODULE_NAME "ULOG"
#define __USE_GNU
#include "../module_iface.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include <linux/netfilter_ipv4/ipt_ULOG.h>
static void setup(void *myinfo, unsigned int *nfcache) {
MODULE_DATATYPE *info = (void *)((MODULE_ENTRYTYPE *)myinfo)->data;
info->nl_group = 1;
info->copy_range = 0;
info->qthreshold = 1;
*nfcache |= NFC_UNKNOWN;
}
static int get_int_value (SV *value, int *val, char *field, int min, int max) {
char *temp, *str, *extent;
STRLEN len;
if(SvIOK(value)) {
*val = SvIV(value);
if(*val < min || *val > max) {
SET_ERRSTR("%s: Integer value %d out of range %d..%d", field, *val,
min, max);
return(FALSE);
}
return(TRUE);
}
else if(SvPOK(value)) {
temp = SvPV(value, len);
str = malloc(len + 1);
strncpy(str, temp, len);
str[len] = '\0';
*val = strtoul(str, &extent, 10);
if(str + strlen(str) > extent) {
SET_ERRSTR("%s: Unable to parse", field);
goto gi_failed;
}
if(*val < min || *val > max) {
SET_ERRSTR("%s: Integer value %d out of range %d..%d", field, *val,
min, max);
goto gi_failed;
}
return(TRUE);
gi_failed:
free(str);
return(FALSE);
}
else {
SET_ERRSTR("%s: Must have an integer arg", field);
return(FALSE);
}
}
static int parse_field(char *field, SV *value, void *myinfo,
unsigned int *nfcache, struct ipt_entry *entry, int *flags) {
MODULE_DATATYPE *info = (void *)(*(MODULE_ENTRYTYPE **)myinfo)->data;
int val;
if(!strcmp(field, "ulog-nlgroup")) {
if(get_int_value(value, &val, field, 1, 32)) {
info->nl_group = 1 << (val-1);
return(TRUE);
}
}
else if(!strcmp(field, "ulog-copy-range")) {
if(get_int_value(value, &val, field, 0, 1500)) {
info->copy_range = val;
return (TRUE);
}
}
else if(!strcmp(field, "ulog-qthreshold")) {
if(get_int_value(value, &val, field, 1, ULOG_MAX_QLEN)) {
info->qthreshold = val;
return (TRUE);
}
}
else if(!strcmp(field, "ulog-prefix")) {
char *str, *temp;
STRLEN len;
if(!SvPOK(value)) {
SET_ERRSTR("%s: Must be a string value", field);
return(FALSE);
}
temp = SvPV(value, len);
str = malloc(len + 1);
strncpy(str, temp, len);
str[len] = '\0';
strncpy(info->prefix, str, ULOG_PREFIX_LEN);
free(str);
return(TRUE);
}
return(FALSE);
}
static void get_fields(HV *ent_hash, void *myinfo, struct ipt_entry *entry) {
MODULE_DATATYPE *info = (void *)((MODULE_ENTRYTYPE *)myinfo)->data;
int i;
if(strcmp(info->prefix, ""))
hv_store(ent_hash, "ulog-prefix", 11, newSVpv(info->prefix, 0), 0);
hv_store(ent_hash, "ulog-copy-range", 15, newSViv(info->copy_range), 0);
hv_store(ent_hash, "ulog-qthreshold", 15, newSViv(info->qthreshold), 0);
i=0;
while (info->nl_group) {
info->nl_group >>= 1;
i++;
}
if (i==0)
fprintf(stderr, "ulog->nlgroup has invalid value 0\n");
else
hv_store(ent_hash, "ulog-nlgroup", 12, newSViv(i), 0);
}
ModuleDef _module = {
.type = MODULE_TYPE,
.name = MODULE_NAME,
.size = IPT_ALIGN(sizeof(MODULE_DATATYPE)),
.size_uspace = IPT_ALIGN(sizeof(MODULE_DATATYPE)),
.setup = setup,
.parse_field = parse_field,
.get_fields = get_fields,
};
ModuleDef *init(void) {
return(&_module);
}
/* vim: ts=4
*/