/*
* shared library add-on to iptables to add TPROXY target support.
*
* Copyright (C) 2002-2008 BalaBit IT Ltd.
*/
#include <stdio.h>
#include <limits.h>
#include <xtables.h>
#include <linux/netfilter/xt_TPROXY.h>
#include <arpa/inet.h>
enum {
P_PORT = 0,
P_ADDR,
P_MARK,
F_PORT = 1 << P_PORT,
F_ADDR = 1 << P_ADDR,
F_MARK = 1 << P_MARK,
};
#define s struct xt_tproxy_target_info
static const struct xt_option_entry tproxy_tg0_opts[] = {
{.name = "on-port", .id = P_PORT, .type = XTTYPE_PORT,
.flags = XTOPT_MAND | XTOPT_NBO | XTOPT_PUT, XTOPT_POINTER(s, lport)},
{.name = "on-ip", .id = P_ADDR, .type = XTTYPE_HOST},
{.name = "tproxy-mark", .id = P_MARK, .type = XTTYPE_MARKMASK32},
XTOPT_TABLEEND,
};
#undef s
#define s struct xt_tproxy_target_info_v1
static const struct xt_option_entry tproxy_tg1_opts[] = {
{.name = "on-port", .id = P_PORT, .type = XTTYPE_PORT,
.flags = XTOPT_MAND | XTOPT_NBO | XTOPT_PUT, XTOPT_POINTER(s, lport)},
{.name = "on-ip", .id = P_ADDR, .type = XTTYPE_HOST,
.flags = XTOPT_PUT, XTOPT_POINTER(s, laddr)},
{.name = "tproxy-mark", .id = P_MARK, .type = XTTYPE_MARKMASK32},
XTOPT_TABLEEND,
};
#undef s
static void tproxy_tg_help(void)
{
printf(
"TPROXY target options:\n"
" --on-port port Redirect connection to port, or the original port if 0\n"
" --on-ip ip Optionally redirect to the given IP\n"
" --tproxy-mark value[/mask] Mark packets with the given value/mask\n\n");
}
static void tproxy_tg_print(const void *ip, const struct xt_entry_target *target,
int numeric)
{
const struct xt_tproxy_target_info *info = (const void *)target->data;
printf(" TPROXY redirect %s:%u mark 0x%x/0x%x",
xtables_ipaddr_to_numeric((const struct in_addr *)&info->laddr),
ntohs(info->lport), (unsigned int)info->mark_value,
(unsigned int)info->mark_mask);
}
static void
tproxy_tg_print4(const void *ip, const struct xt_entry_target *target,
int numeric)
{
const struct xt_tproxy_target_info_v1 *info =
(const void *)target->data;
printf(" TPROXY redirect %s:%u mark 0x%x/0x%x",
xtables_ipaddr_to_numeric(&info->laddr.in),
ntohs(info->lport), (unsigned int)info->mark_value,
(unsigned int)info->mark_mask);
}
static void
tproxy_tg_print6(const void *ip, const struct xt_entry_target *target,
int numeric)
{
const struct xt_tproxy_target_info_v1 *info =
(const void *)target->data;
printf(" TPROXY redirect %s:%u mark 0x%x/0x%x",
xtables_ip6addr_to_numeric(&info->laddr.in6),
ntohs(info->lport), (unsigned int)info->mark_value,
(unsigned int)info->mark_mask);
}
static void tproxy_tg_save(const void *ip, const struct xt_entry_target *target)
{
const struct xt_tproxy_target_info *info = (const void *)target->data;
printf(" --on-port %u", ntohs(info->lport));
printf(" --on-ip %s",
xtables_ipaddr_to_numeric((const struct in_addr *)&info->laddr));
printf(" --tproxy-mark 0x%x/0x%x",
(unsigned int)info->mark_value, (unsigned int)info->mark_mask);
}
static void
tproxy_tg_save4(const void *ip, const struct xt_entry_target *target)
{
const struct xt_tproxy_target_info_v1 *info;
info = (const void *)target->data;
printf(" --on-port %u", ntohs(info->lport));
printf(" --on-ip %s", xtables_ipaddr_to_numeric(&info->laddr.in));
printf(" --tproxy-mark 0x%x/0x%x",
(unsigned int)info->mark_value, (unsigned int)info->mark_mask);
}
static void
tproxy_tg_save6(const void *ip, const struct xt_entry_target *target)
{
const struct xt_tproxy_target_info_v1 *info;
info = (const void *)target->data;
printf(" --on-port %u", ntohs(info->lport));
printf(" --on-ip %s", xtables_ip6addr_to_numeric(&info->laddr.in6));
printf(" --tproxy-mark 0x%x/0x%x",
(unsigned int)info->mark_value, (unsigned int)info->mark_mask);
}
static void tproxy_tg0_parse(struct xt_option_call *cb)
{
struct xt_tproxy_target_info *info = cb->data;
xtables_option_parse(cb);
switch (cb->entry->id) {
case P_MARK:
info->mark_value = cb->val.mark;
info->mark_mask = cb->val.mask;
break;
case P_ADDR:
info->laddr = cb->val.haddr.ip;
break;
}
}
static void tproxy_tg1_parse(struct xt_option_call *cb)
{
struct xt_tproxy_target_info_v1 *info = cb->data;
xtables_option_parse(cb);
switch (cb->entry->id) {
case P_MARK:
info->mark_value = cb->val.mark;
info->mark_mask = cb->val.mask;
break;
}
}
static struct xtables_target tproxy_tg_reg[] = {
{
.name = "TPROXY",
.revision = 0,
.family = NFPROTO_IPV4,
.version = XTABLES_VERSION,
.size = XT_ALIGN(sizeof(struct xt_tproxy_target_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_tproxy_target_info)),
.help = tproxy_tg_help,
.print = tproxy_tg_print,
.save = tproxy_tg_save,
.x6_options = tproxy_tg0_opts,
.x6_parse = tproxy_tg0_parse,
},
{
.name = "TPROXY",
.revision = 1,
.family = NFPROTO_IPV4,
.version = XTABLES_VERSION,
.size = XT_ALIGN(sizeof(struct xt_tproxy_target_info_v1)),
.userspacesize = XT_ALIGN(sizeof(struct xt_tproxy_target_info_v1)),
.help = tproxy_tg_help,
.print = tproxy_tg_print4,
.save = tproxy_tg_save4,
.x6_options = tproxy_tg1_opts,
.x6_parse = tproxy_tg1_parse,
},
{
.name = "TPROXY",
.revision = 1,
.family = NFPROTO_IPV6,
.version = XTABLES_VERSION,
.size = XT_ALIGN(sizeof(struct xt_tproxy_target_info_v1)),
.userspacesize = XT_ALIGN(sizeof(struct xt_tproxy_target_info_v1)),
.help = tproxy_tg_help,
.print = tproxy_tg_print6,
.save = tproxy_tg_save6,
.x6_options = tproxy_tg1_opts,
.x6_parse = tproxy_tg1_parse,
},
};
void _init(void)
{
xtables_register_targets(tproxy_tg_reg, ARRAY_SIZE(tproxy_tg_reg));
}