kernel modules:
#include <linux/types.h>
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/netfilter.h>
#include <linux/netfilter/x_tables.h>
#define DRV_VERSION "1.0"
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
MODULE_DESCRIPTION("Xtables: TARGET print");
struct id {
unsigned char id;
};
static int target_check(const struct xt_tgchk_param *par)
{
const struct id *mr = par->targinfo;
if (mr->id == 0) {
pr_info("%s: id must not be 0\n",
par->target->name);
return -EINVAL;
}
return 0;
}
static unsigned int
target_tg(struct sk_buff *skb, const struct xt_action_param *par)
{
const struct id *mr = par->targinfo;
printk("just test target id: %u, hooknum %u\n", mr->id, par->hooknum);
return XT_CONTINUE;
}
static struct xt_target target_reg __read_mostly = {
.name = "TARGET",
.family = NFPROTO_IPV4,
.target = target_tg,
.targetsize = sizeof(struct id),
//.table = "mangle",
.hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_IN),
.checkentry = target_check,
.me = THIS_MODULE,
};
static int __init target_target_init(void)
{
return xt_register_target(&target_reg);
}
static void __exit target_target_exit(void)
{
xt_unregister_target(&target_reg);
}
module_init(target_target_init);
module_exit(target_target_exit);
userspace so:
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <xtables.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
enum {
FROM_TARGET = 0,
};
#define MAX 64
struct id {
unsigned char id;
};
struct ipt_targetinfo
{
struct xt_entry_target t;
struct id mr;
};
static void TARGET_help(void)
{
printf(
"TARGET target options:\n"
" --set-id id <id 1-255>\\n");
}
static const struct xt_option_entry TARGET_opts[] = {
{
.name = "set-id",
.id = FROM_TARGET,
.type = XTTYPE_UINT8,
.flags = XTOPT_MAND,
.min = 1
},
XTOPT_TABLEEND,
};
static void TARGET_parse(struct xt_option_call *cb)
{
struct ipt_targetinfo *info = (void *)(*cb->target);
xtables_option_parse(cb);
switch (cb->entry->id) {
case FROM_TARGET: {
info->mr.id = cb->val.u8;
break;
}
}
}
static void TARGET_save(const void *ip, const struct xt_entry_target *target)
{
const struct ipt_targetinfo *info = (const void *)target;
unsigned int i = 0;
printf(" --set-id %u\n", info->mr.id);
}
static struct xtables_target target_tg_reg = {
.name = "TARGET",
.version = XTABLES_VERSION,
.family = NFPROTO_IPV4,
.size = XT_ALIGN(sizeof(struct id)),
.userspacesize = XT_ALIGN(sizeof(struct id)),
.help = TARGET_help,
.x6_parse = TARGET_parse,
.save = TARGET_save,
.x6_options = TARGET_opts,
};
void _init(void)
{
xtables_register_target(&target_tg_reg);
}
Makefile:
CC=gcc
PWD = $(shell pwd)
IPTABLES_SRC = $(PWD)/iptables-1.4.21
INCLUDE = -I$(IPTABLES_SRC)/include
KERNEL_SRC = /lib/modules/`uname -r`/build
obj-m = ipt_TARGET.o
all: ipt_TARGET.ko ibipt_TARGET.so
ipt_TARGET.ko: ipt_TARGET.c
$(MAKE) -C $(KERNEL_SRC) SUBDIRS=$(PWD) modules
libipt_TARGET.so: libipt_TARGET.c
$(CC) $(INCLUDE) -fPIC -c libipt_TARGET.c
ld -shared -o libipt_TARGET.so libipt_TARGET.o
usage:
iptables -t mangle -A PREROUTING -s x.x.x.x/24 -j TARGET --set-id 100