Commit 7e95a8db authored by Arturo Borrero Gonzalez's avatar Arturo Borrero Gonzalez
Browse files

Imported Upstream version 1.4.21

parents
/* Shared library add-on to iptables for DSCP
*
* (C) 2000- 2002 by Matthew G. Marsh <mgm@paktronix.com>,
* Harald Welte <laforge@gnumonks.org>
*
* This program is distributed under the terms of GNU GPL v2, 1991
*
* libipt_DSCP.c borrowed heavily from libipt_TOS.c
*
* --set-class added by Iain Barnes
*/
#include <stdio.h>
#include <string.h>
#include <xtables.h>
#include <linux/netfilter/xt_DSCP.h>
/* This is evil, but it's my code - HW*/
#include "dscp_helper.c"
enum {
O_SET_DSCP = 0,
O_SET_DSCP_CLASS,
F_SET_DSCP = 1 << O_SET_DSCP,
F_SET_DSCP_CLASS = 1 << O_SET_DSCP_CLASS,
};
static void DSCP_help(void)
{
printf(
"DSCP target options\n"
" --set-dscp value Set DSCP field in packet header to value\n"
" This value can be in decimal (ex: 32)\n"
" or in hex (ex: 0x20)\n"
" --set-dscp-class class Set the DSCP field in packet header to the\n"
" value represented by the DiffServ class value.\n"
" This class may be EF,BE or any of the CSxx\n"
" or AFxx classes.\n"
"\n"
" These two options are mutually exclusive !\n"
);
}
static const struct xt_option_entry DSCP_opts[] = {
{.name = "set-dscp", .id = O_SET_DSCP, .excl = F_SET_DSCP_CLASS,
.type = XTTYPE_UINT8, .min = 0, .max = XT_DSCP_MAX,
.flags = XTOPT_PUT,
XTOPT_POINTER(struct xt_DSCP_info, dscp)},
{.name = "set-dscp-class", .id = O_SET_DSCP_CLASS, .excl = F_SET_DSCP,
.type = XTTYPE_STRING},
XTOPT_TABLEEND,
};
static void DSCP_parse(struct xt_option_call *cb)
{
struct xt_DSCP_info *dinfo = cb->data;
xtables_option_parse(cb);
switch (cb->entry->id) {
case O_SET_DSCP_CLASS:
dinfo->dscp = class_to_dscp(cb->arg);
break;
}
}
static void DSCP_check(struct xt_fcheck_call *cb)
{
if (cb->xflags == 0)
xtables_error(PARAMETER_PROBLEM,
"DSCP target: Parameter --set-dscp is required");
}
static void
print_dscp(uint8_t dscp, int numeric)
{
printf(" 0x%02x", dscp);
}
static void DSCP_print(const void *ip, const struct xt_entry_target *target,
int numeric)
{
const struct xt_DSCP_info *dinfo =
(const struct xt_DSCP_info *)target->data;
printf(" DSCP set");
print_dscp(dinfo->dscp, numeric);
}
static void DSCP_save(const void *ip, const struct xt_entry_target *target)
{
const struct xt_DSCP_info *dinfo =
(const struct xt_DSCP_info *)target->data;
printf(" --set-dscp 0x%02x", dinfo->dscp);
}
static struct xtables_target dscp_target = {
.family = NFPROTO_UNSPEC,
.name = "DSCP",
.version = XTABLES_VERSION,
.size = XT_ALIGN(sizeof(struct xt_DSCP_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_DSCP_info)),
.help = DSCP_help,
.print = DSCP_print,
.save = DSCP_save,
.x6_parse = DSCP_parse,
.x6_fcheck = DSCP_check,
.x6_options = DSCP_opts,
};
void _init(void)
{
xtables_register_target(&dscp_target);
}
This target allows to alter the value of the DSCP bits within the TOS
header of the IPv4 packet. As this manipulates a packet, it can only
be used in the mangle table.
.TP
\fB\-\-set\-dscp\fP \fIvalue\fP
Set the DSCP field to a numerical value (can be decimal or hex)
.TP
\fB\-\-set\-dscp\-class\fP \fIclass\fP
Set the DSCP field to a DiffServ class.
/*
* (C) 2012 by Hans Schillstrom <hans.schillstrom@ericsson.com>
* (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Description: shared library add-on to iptables to add HMARK target support
*
* Initial development by Hans Schillstrom. Pablo's improvements to this piece
* of software has been sponsored by Sophos Astaro <http://www.sophos.com>.
*/
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include "xtables.h"
#include <linux/netfilter/xt_HMARK.h>
static void HMARK_help(void)
{
printf(
"HMARK target options, i.e. modify hash calculation by:\n"
" --hmark-tuple [src|dst|sport|dport|spi|proto|ct][,...]\n"
" --hmark-mod value nfmark modulus value\n"
" --hmark-offset value Last action add value to nfmark\n\n"
" --hmark-rnd Random see for hashing\n"
" Alternatively, fine tuning of what will be included in hash calculation\n"
" --hmark-src-prefix length Source address mask CIDR prefix\n"
" --hmark-dst-prefix length Dest address mask CIDR prefix\n"
" --hmark-sport-mask value Mask src port with value\n"
" --hmark-dport-mask value Mask dst port with value\n"
" --hmark-spi-mask value For esp and ah AND spi with value\n"
" --hmark-sport value OR src port with value\n"
" --hmark-dport value OR dst port with value\n"
" --hmark-spi value For esp and ah OR spi with value\n"
" --hmark-proto-mask value Mask Protocol with value\n");
}
#define hi struct xt_hmark_info
enum {
O_HMARK_SADDR_MASK,
O_HMARK_DADDR_MASK,
O_HMARK_SPI,
O_HMARK_SPI_MASK,
O_HMARK_SPORT,
O_HMARK_DPORT,
O_HMARK_SPORT_MASK,
O_HMARK_DPORT_MASK,
O_HMARK_PROTO_MASK,
O_HMARK_RND,
O_HMARK_MODULUS,
O_HMARK_OFFSET,
O_HMARK_CT,
O_HMARK_TYPE,
};
#define HMARK_OPT_PKT_MASK \
((1 << O_HMARK_SADDR_MASK) | \
(1 << O_HMARK_DADDR_MASK) | \
(1 << O_HMARK_SPI_MASK) | \
(1 << O_HMARK_SPORT_MASK) | \
(1 << O_HMARK_DPORT_MASK) | \
(1 << O_HMARK_PROTO_MASK) | \
(1 << O_HMARK_SPI_MASK) | \
(1 << O_HMARK_SPORT) | \
(1 << O_HMARK_DPORT) | \
(1 << O_HMARK_SPI))
static const struct xt_option_entry HMARK_opts[] = {
{ .name = "hmark-tuple",
.type = XTTYPE_STRING,
.id = O_HMARK_TYPE,
},
{ .name = "hmark-src-prefix",
.type = XTTYPE_PLENMASK,
.id = O_HMARK_SADDR_MASK,
.flags = XTOPT_PUT, XTOPT_POINTER(hi, src_mask)
},
{ .name = "hmark-dst-prefix",
.type = XTTYPE_PLENMASK,
.id = O_HMARK_DADDR_MASK,
.flags = XTOPT_PUT, XTOPT_POINTER(hi, dst_mask)
},
{ .name = "hmark-sport-mask",
.type = XTTYPE_UINT16,
.id = O_HMARK_SPORT_MASK,
.flags = XTOPT_PUT, XTOPT_POINTER(hi, port_mask.p16.src)
},
{ .name = "hmark-dport-mask",
.type = XTTYPE_UINT16,
.id = O_HMARK_DPORT_MASK,
.flags = XTOPT_PUT, XTOPT_POINTER(hi, port_mask.p16.dst)
},
{ .name = "hmark-spi-mask",
.type = XTTYPE_UINT32,
.id = O_HMARK_SPI_MASK,
.flags = XTOPT_PUT, XTOPT_POINTER(hi, port_mask.v32)
},
{ .name = "hmark-sport",
.type = XTTYPE_UINT16,
.id = O_HMARK_SPORT,
.flags = XTOPT_PUT, XTOPT_POINTER(hi, port_set.p16.src)
},
{ .name = "hmark-dport",
.type = XTTYPE_UINT16,
.id = O_HMARK_DPORT,
.flags = XTOPT_PUT, XTOPT_POINTER(hi, port_set.p16.dst)
},
{ .name = "hmark-spi",
.type = XTTYPE_UINT32,
.id = O_HMARK_SPI,
.flags = XTOPT_PUT, XTOPT_POINTER(hi, port_set.v32)
},
{ .name = "hmark-proto-mask",
.type = XTTYPE_UINT16,
.id = O_HMARK_PROTO_MASK,
.flags = XTOPT_PUT, XTOPT_POINTER(hi, proto_mask)
},
{ .name = "hmark-rnd",
.type = XTTYPE_UINT32,
.id = O_HMARK_RND,
.flags = XTOPT_PUT, XTOPT_POINTER(hi, hashrnd)
},
{ .name = "hmark-mod",
.type = XTTYPE_UINT32,
.id = O_HMARK_MODULUS,
.min = 1,
.flags = XTOPT_PUT | XTOPT_MAND, XTOPT_POINTER(hi, hmodulus)
},
{ .name = "hmark-offset",
.type = XTTYPE_UINT32,
.id = O_HMARK_OFFSET,
.flags = XTOPT_PUT, XTOPT_POINTER(hi, hoffset)
},
XTOPT_TABLEEND,
};
static int
hmark_parse(const char *type, size_t len, struct xt_hmark_info *info,
unsigned int *xflags)
{
if (strncasecmp(type, "ct", len) == 0) {
info->flags |= XT_HMARK_FLAG(XT_HMARK_CT);
*xflags |= (1 << O_HMARK_CT);
} else if (strncasecmp(type, "src", len) == 0) {
memset(&info->src_mask, 0xff, sizeof(info->src_mask));
info->flags |= XT_HMARK_FLAG(XT_HMARK_SADDR_MASK);
*xflags |= (1 << O_HMARK_SADDR_MASK);
} else if (strncasecmp(type, "dst", len) == 0) {
memset(&info->dst_mask, 0xff, sizeof(info->dst_mask));
info->flags |= XT_HMARK_FLAG(XT_HMARK_DADDR_MASK);
*xflags |= (1 << O_HMARK_DADDR_MASK);
} else if (strncasecmp(type, "sport", len) == 0) {
memset(&info->port_mask.p16.src, 0xff,
sizeof(info->port_mask.p16.src));
info->flags |= XT_HMARK_FLAG(XT_HMARK_SPORT_MASK);
*xflags |= (1 << O_HMARK_SPORT_MASK);
} else if (strncasecmp(type, "dport", len) == 0) {
memset(&info->port_mask.p16.dst, 0xff,
sizeof(info->port_mask.p16.dst));
info->flags |= XT_HMARK_FLAG(XT_HMARK_DPORT_MASK);
*xflags |= (1 << O_HMARK_DPORT_MASK);
} else if (strncasecmp(type, "proto", len) == 0) {
memset(&info->proto_mask, 0xff, sizeof(info->proto_mask));
info->flags |= XT_HMARK_FLAG(XT_HMARK_PROTO_MASK);
*xflags |= (1 << O_HMARK_PROTO_MASK);
} else if (strncasecmp(type, "spi", len) == 0) {
memset(&info->port_mask.v32, 0xff, sizeof(info->port_mask.v32));
info->flags |= XT_HMARK_FLAG(XT_HMARK_SPI_MASK);
*xflags |= (1 << O_HMARK_SPI_MASK);
} else
return 0;
return 1;
}
static void
hmark_parse_type(struct xt_option_call *cb)
{
const char *arg = cb->arg;
struct xt_hmark_info *info = cb->data;
const char *comma;
while ((comma = strchr(arg, ',')) != NULL) {
if (comma == arg ||
!hmark_parse(arg, comma-arg, info, &cb->xflags))
xtables_error(PARAMETER_PROBLEM, "Bad type \"%s\"", arg);
arg = comma+1;
}
if (!*arg)
xtables_error(PARAMETER_PROBLEM, "\"--hmark-tuple\" requires "
"a list of types with no "
"spaces, e.g. "
"src,dst,sport,dport,proto");
if (strlen(arg) == 0 ||
!hmark_parse(arg, strlen(arg), info, &cb->xflags))
xtables_error(PARAMETER_PROBLEM, "Bad type \"%s\"", arg);
}
static void HMARK_parse(struct xt_option_call *cb, int plen)
{
struct xt_hmark_info *info = cb->data;
xtables_option_parse(cb);
switch (cb->entry->id) {
case O_HMARK_TYPE:
hmark_parse_type(cb);
break;
case O_HMARK_SADDR_MASK:
info->flags |= XT_HMARK_FLAG(XT_HMARK_SADDR_MASK);
break;
case O_HMARK_DADDR_MASK:
info->flags |= XT_HMARK_FLAG(XT_HMARK_DADDR_MASK);
break;
case O_HMARK_SPI:
info->port_set.v32 = htonl(cb->val.u32);
info->flags |= XT_HMARK_FLAG(XT_HMARK_SPI);
break;
case O_HMARK_SPORT:
info->port_set.p16.src = htons(cb->val.u16);
info->flags |= XT_HMARK_FLAG(XT_HMARK_SPORT);
break;
case O_HMARK_DPORT:
info->port_set.p16.dst = htons(cb->val.u16);
info->flags |= XT_HMARK_FLAG(XT_HMARK_DPORT);
break;
case O_HMARK_SPORT_MASK:
info->port_mask.p16.src = htons(cb->val.u16);
info->flags |= XT_HMARK_FLAG(XT_HMARK_SPORT_MASK);
break;
case O_HMARK_DPORT_MASK:
info->port_mask.p16.dst = htons(cb->val.u16);
info->flags |= XT_HMARK_FLAG(XT_HMARK_DPORT_MASK);
break;
case O_HMARK_SPI_MASK:
info->port_mask.v32 = htonl(cb->val.u32);
info->flags |= XT_HMARK_FLAG(XT_HMARK_SPI_MASK);
break;
case O_HMARK_PROTO_MASK:
info->flags |= XT_HMARK_FLAG(XT_HMARK_PROTO_MASK);
break;
case O_HMARK_RND:
info->flags |= XT_HMARK_FLAG(XT_HMARK_RND);
break;
case O_HMARK_MODULUS:
info->flags |= XT_HMARK_FLAG(XT_HMARK_MODULUS);
break;
case O_HMARK_OFFSET:
info->flags |= XT_HMARK_FLAG(XT_HMARK_OFFSET);
break;
case O_HMARK_CT:
info->flags |= XT_HMARK_FLAG(XT_HMARK_CT);
break;
}
cb->xflags |= (1 << cb->entry->id);
}
static void HMARK_ip4_parse(struct xt_option_call *cb)
{
HMARK_parse(cb, 32);
}
static void HMARK_ip6_parse(struct xt_option_call *cb)
{
HMARK_parse(cb, 128);
}
static void HMARK_check(struct xt_fcheck_call *cb)
{
if (!(cb->xflags & (1 << O_HMARK_MODULUS)))
xtables_error(PARAMETER_PROBLEM, "--hmark-mod is mandatory");
if (!(cb->xflags & (1 << O_HMARK_RND)))
xtables_error(PARAMETER_PROBLEM, "--hmark-rnd is mandatory");
if (cb->xflags & (1 << O_HMARK_SPI_MASK) &&
(cb->xflags & ((1 << O_HMARK_SPORT_MASK) |
(1 << O_HMARK_DPORT_MASK))))
xtables_error(PARAMETER_PROBLEM, "you cannot use "
"--hmark-spi-mask and --hmark-?port-mask,"
"at the same time");
if (!((cb->xflags & HMARK_OPT_PKT_MASK) ||
cb->xflags & (1 << O_HMARK_CT)))
xtables_error(PARAMETER_PROBLEM, "you have to specify "
"--hmark-tuple at least");
}
static void HMARK_print(const struct xt_hmark_info *info)
{
if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT_MASK))
printf("sport-mask 0x%x ", htons(info->port_mask.p16.src));
if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT_MASK))
printf("dport-mask 0x%x ", htons(info->port_mask.p16.dst));
if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI_MASK))
printf("spi-mask 0x%x ", htonl(info->port_mask.v32));
if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT))
printf("sport 0x%x ", htons(info->port_set.p16.src));
if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT))
printf("dport 0x%x ", htons(info->port_set.p16.dst));
if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI))
printf("spi 0x%x ", htonl(info->port_set.v32));
if (info->flags & XT_HMARK_FLAG(XT_HMARK_PROTO_MASK))
printf("proto-mask 0x%x ", info->proto_mask);
if (info->flags & XT_HMARK_FLAG(XT_HMARK_RND))
printf("rnd 0x%x ", info->hashrnd);
}
static void HMARK_ip6_print(const void *ip,
const struct xt_entry_target *target, int numeric)
{
const struct xt_hmark_info *info =
(const struct xt_hmark_info *)target->data;
printf(" HMARK ");
if (info->flags & XT_HMARK_FLAG(XT_HMARK_MODULUS))
printf("mod %u ", info->hmodulus);
if (info->flags & XT_HMARK_FLAG(XT_HMARK_OFFSET))
printf("+ 0x%x ", info->hoffset);
if (info->flags & XT_HMARK_FLAG(XT_HMARK_CT))
printf("ct, ");
if (info->flags & XT_HMARK_FLAG(XT_HMARK_SADDR_MASK))
printf("src-prefix %s ",
xtables_ip6mask_to_numeric(&info->src_mask.in6) + 1);
if (info->flags & XT_HMARK_FLAG(XT_HMARK_DADDR_MASK))
printf("dst-prefix %s ",
xtables_ip6mask_to_numeric(&info->dst_mask.in6) + 1);
HMARK_print(info);
}
static void HMARK_ip4_print(const void *ip,
const struct xt_entry_target *target, int numeric)
{
const struct xt_hmark_info *info =
(const struct xt_hmark_info *)target->data;
printf(" HMARK ");
if (info->flags & XT_HMARK_FLAG(XT_HMARK_MODULUS))
printf("mod %u ", info->hmodulus);
if (info->flags & XT_HMARK_FLAG(XT_HMARK_OFFSET))
printf("+ 0x%x ", info->hoffset);
if (info->flags & XT_HMARK_FLAG(XT_HMARK_CT))
printf("ct, ");
if (info->flags & XT_HMARK_FLAG(XT_HMARK_SADDR_MASK))
printf("src-prefix %u ",
xtables_ipmask_to_cidr(&info->src_mask.in));
if (info->flags & XT_HMARK_FLAG(XT_HMARK_DADDR_MASK))
printf("dst-prefix %u ",
xtables_ipmask_to_cidr(&info->dst_mask.in));
HMARK_print(info);
}
static void HMARK_save(const struct xt_hmark_info *info)
{
if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT_MASK))
printf(" --hmark-sport-mask 0x%04x",
htons(info->port_mask.p16.src));
if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT_MASK))
printf(" --hmark-dport-mask 0x%04x",
htons(info->port_mask.p16.dst));
if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI_MASK))
printf(" --hmark-spi-mask 0x%08x",
htonl(info->port_mask.v32));
if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPORT))
printf(" --hmark-sport 0x%04x",
htons(info->port_set.p16.src));
if (info->flags & XT_HMARK_FLAG(XT_HMARK_DPORT))
printf(" --hmark-dport 0x%04x",
htons(info->port_set.p16.dst));
if (info->flags & XT_HMARK_FLAG(XT_HMARK_SPI))
printf(" --hmark-spi 0x%08x", htonl(info->port_set.v32));
if (info->flags & XT_HMARK_FLAG(XT_HMARK_PROTO_MASK))
printf(" --hmark-proto-mask 0x%02x", info->proto_mask);
if (info->flags & XT_HMARK_FLAG(XT_HMARK_RND))
printf(" --hmark-rnd 0x%08x", info->hashrnd);
if (info->flags & XT_HMARK_FLAG(XT_HMARK_MODULUS))
printf(" --hmark-mod %u", info->hmodulus);
if (info->flags & XT_HMARK_FLAG(XT_HMARK_OFFSET))
printf(" --hmark-offset %u", info->hoffset);
if (info->flags & XT_HMARK_FLAG(XT_HMARK_CT))
printf(" --hmark-tuple ct");
}
static void HMARK_ip6_save(const void *ip, const struct xt_entry_target *target)
{
const struct xt_hmark_info *info =
(const struct xt_hmark_info *)target->data;
int ret;
if (info->flags & XT_HMARK_FLAG(XT_HMARK_SADDR_MASK)) {
ret = xtables_ip6mask_to_cidr(&info->src_mask.in6);
printf(" --hmark-src-prefix %d", ret);
}
if (info->flags & XT_HMARK_FLAG(XT_HMARK_DADDR_MASK)) {
ret = xtables_ip6mask_to_cidr(&info->dst_mask.in6);
printf(" --hmark-dst-prefix %d", ret);
}
HMARK_save(info);
}
static void HMARK_ip4_save(const void *ip, const struct xt_entry_target *target)
{
const struct xt_hmark_info *info =
(const struct xt_hmark_info *)target->data;
int ret;
if (info->flags & XT_HMARK_FLAG(XT_HMARK_SADDR_MASK)) {
ret = xtables_ipmask_to_cidr(&info->src_mask.in);
printf(" --hmark-src-prefix %d", ret);
}
if (info->flags & XT_HMARK_FLAG(XT_HMARK_DADDR_MASK)) {
ret = xtables_ipmask_to_cidr(&info->dst_mask.in);
printf(" --hmark-dst-prefix %d", ret);
}
HMARK_save(info);
}
static struct xtables_target mark_tg_reg[] = {
{
.family = NFPROTO_IPV4,
.name = "HMARK",
.version = XTABLES_VERSION,
.size = XT_ALIGN(sizeof(struct xt_hmark_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_hmark_info)),
.help = HMARK_help,
.print = HMARK_ip4_print,
.save = HMARK_ip4_save,
.x6_parse = HMARK_ip4_parse,
.x6_fcheck = HMARK_check,
.x6_options = HMARK_opts,
},
{
.family = NFPROTO_IPV6,
.name = "HMARK",
.version = XTABLES_VERSION,
.size = XT_ALIGN(sizeof(struct xt_hmark_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_hmark_info)),
.help = HMARK_help,
.print = HMARK_ip6_print,
.save = HMARK_ip6_save,
.x6_parse = HMARK_ip6_parse,
.x6_fcheck = HMARK_check,
.x6_options = HMARK_opts,
},
};
void _init(void)
{
xtables_register_targets(mark_tg_reg, ARRAY_SIZE(mark_tg_reg));
}
Like MARK, i.e. set the fwmark, but the mark is calculated from hashing
packet selector at choice. You have also to specify the mark range and,
optionally, the offset to start from. ICMP error messages are inspected
and used to calculate the hashing.
.PP
Existing options are:
.TP
\fB\-\-hmark\-tuple\fP tuple\fI\fP
Possible tuple members are:
.B src
meaning source address (IPv4, IPv6 address),
.B dst
meaning destination address (IPv4, IPv6 address),
.B sport
meaning source port (TCP, UDP, UDPlite, SCTP, DCCP),
.B dport
meaning destination port (TCP, UDP, UDPlite, SCTP, DCCP),
.B spi
meaning Security Parameter Index (AH, ESP), and
.B ct
meaning the usage of the conntrack tuple instead of the packet selectors.
.TP
\fB\-\-hmark\-mod\fP \fIvalue (must be > 0)\fP
Modulus for hash calculation (to limit the range of possible marks)
.TP
\fB\-\-hmark\-offset\fP \fIvalue\fP
Offset to start marks from.
.TP
For advanced usage, instead of using \-\-hmark\-tuple, you can specify custom
prefixes and masks:
.TP
\fB\-\-hmark\-src\-prefix\fP \fIcidr\fP
The source address mask in CIDR notation.
.TP
\fB\-\-hmark\-dst\-prefix\fP \fIcidr\fP
The destination address mask in CIDR notation.
.TP
\fB\-\-hmark\-sport\-mask\fP \fIvalue\fP
A 16 bit source port mask in hexadecimal.
.TP
\fB\-\-hmark\-dport\-mask\fP \fIvalue\fP
A 16 bit destination port mask in hexadecimal.
.TP
\fB\-\-hmark\-spi\-mask\fP \fIvalue\fP
A 32 bit field with spi mask.
.TP
\fB\-\-hmark\-proto\-mask\fP \fIvalue\fP
An 8 bit field with layer 4 protocol number.
.TP
\fB\-\-hmark\-rnd\fP \fIvalue\fP
A 32 bit random custom value to feed hash calculation.
.PP
\fIExamples:\fP
.PP
iptables \-t mangle \-A PREROUTING \-m conntrack \-\-ctstate NEW
\-j HMARK \-\-hmark-tuple ct,src,dst,proto \-\-hmark-offset 10000
\-\-hmark\-mod 10 \-\-hmark\-rnd 0xfeedcafe
.PP
iptables \-t mangle \-A PREROUTING -j HMARK \-\-hmark\-offset 10000
\-\-hmark-tuple src,dst,proto \-\-hmark-mod 10 \-\-hmark\-rnd 0xdeafbeef
/*
* Shared library add-on for iptables to add IDLETIMER support.
*
* Copyright (C) 2010 Nokia Corporation. All rights reserved.
*
* Contact: Luciano Coelho <luciano.coelho@nokia.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#include <stdio.h>
#include <xtables.h>
#include <linux/netfilter/xt_IDLETIMER.h>
enum {
O_TIMEOUT = 0,
O_LABEL,
};
#define s struct idletimer_tg_info
static const struct xt_option_entry idletimer_tg_opts[] = {
{.name = "timeout", .id = O_TIMEOUT, .type = XTTYPE_UINT32,
.flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, timeout)},
{.name = "label", .id = O_LABEL, .type = XTTYPE_STRING,
.flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, label)},
XTOPT_TABLEEND,
};
#undef s
static void idletimer_tg_help(void)
{
printf(
"IDLETIMER target options:\n"
" --timeout time Timeout until the notification is sent (in seconds)\n"
" --label string Unique rule identifier\n"
"\n");
}
static void idletimer_tg_print(const void *ip,
const struct xt_entry_target *target,
int numeric)
{
struct idletimer_tg_info *info =
(struct idletimer_tg_info *) target->data;
printf(" timeout:%u", info->timeout);
printf(" label:%s", info->label);
}
static void idletimer_tg_save(const void *ip,
const struct xt_entry_target *target)
{
struct idletimer_tg_info *info =
(struct idletimer_tg_info *) target->data;
printf(" --timeout %u", info->timeout);
printf(" --label %s", info->label);
}
static struct xtables_target idletimer_tg_reg = {
.family = NFPROTO_UNSPEC,
.name = "IDLETIMER",
.version = XTABLES_VERSION,
.revision = 0,
.size = XT_ALIGN(sizeof(struct idletimer_tg_info)),
.userspacesize = offsetof(struct idletimer_tg_info, timer),
.help = idletimer_tg_help,
.x6_parse = xtables_option_parse,
.print = idletimer_tg_print,
.save = idletimer_tg_save,
.x6_options = idletimer_tg_opts,
};
void _init(void)
{
xtables_register_target(&idletimer_tg_reg);
}
This target can be used to identify when interfaces have been idle for a
certain period of time. Timers are identified by labels and are created when
a rule is set with a new label. The rules also take a timeout value (in
seconds) as an option. If more than one rule uses the same timer label, the
timer will be restarted whenever any of the rules get a hit. One entry for
each timer is created in sysfs. This attribute contains the timer remaining
for the timer to expire. The attributes are located under the xt_idletimer
class:
.PP
/sys/class/xt_idletimer/timers/<label>
.PP
When the timer expires, the target module sends a sysfs notification to the
userspace, which can then decide what to do (eg. disconnect to save power).
.TP
\fB\-\-timeout\fP \fIamount\fP
This is the time in seconds that will trigger the notification.
.TP
\fB\-\-label\fP \fIstring\fP
This is a unique identifier for the timer. The maximum length for the
label string is 27 characters.
/*
* libxt_LED.c - shared library add-on to iptables to add customized LED
* trigger support.
*
* (C) 2008 Adam Nielsen <a.nielsen@shikadi.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <xtables.h>
#include <linux/netfilter/xt_LED.h>
enum {
O_LED_TRIGGER_ID = 0,
O_LED_DELAY,
O_LED_ALWAYS_BLINK,
};
#define s struct xt_led_info
static const struct xt_option_entry LED_opts[] = {
{.name = "led-trigger-id", .id = O_LED_TRIGGER_ID,
.flags = XTOPT_MAND, .type = XTTYPE_STRING, .min = 0,
.max = sizeof(((struct xt_led_info *)NULL)->id) -
sizeof("netfilter-")},
{.name = "led-delay", .id = O_LED_DELAY, .type = XTTYPE_STRING},
{.name = "led-always-blink", .id = O_LED_ALWAYS_BLINK,
.type = XTTYPE_NONE},
XTOPT_TABLEEND,
};
#undef s
static void LED_help(void)
{
printf(
"LED target options:\n"
"--led-trigger-id name suffix for led trigger name\n"
"--led-delay ms leave the LED on for this number of\n"
" milliseconds after triggering.\n"
"--led-always-blink blink on arriving packets, even if\n"
" the LED is already on.\n"
);
}
static void LED_parse(struct xt_option_call *cb)
{
struct xt_led_info *led = cb->data;
xtables_option_parse(cb);
switch (cb->entry->id) {
case O_LED_TRIGGER_ID:
strcpy(led->id, "netfilter-");
strcat(led->id, cb->arg);
break;
case O_LED_DELAY:
if (strncasecmp(cb->arg, "inf", 3) == 0)
led->delay = -1;
else if (!xtables_strtoui(cb->arg, NULL, &led->delay, 0, UINT32_MAX))
xtables_error(PARAMETER_PROBLEM,
"Delay value must be within range 0..%u",
UINT32_MAX);
break;
case O_LED_ALWAYS_BLINK:
led->always_blink = 1;
break;
}
}
static void LED_print(const void *ip, const struct xt_entry_target *target,
int numeric)
{
const struct xt_led_info *led = (void *)target->data;
const char *id = led->id + strlen("netfilter-"); /* trim off prefix */
printf(" led-trigger-id:\"");
/* Escape double quotes and backslashes in the ID */
while (*id != '\0') {
if (*id == '"' || *id == '\\')
printf("\\");
printf("%c", *id++);
}
printf("\"");
if (led->delay == -1)
printf(" led-delay:inf");
else
printf(" led-delay:%dms", led->delay);
if (led->always_blink)
printf(" led-always-blink");
}
static void LED_save(const void *ip, const struct xt_entry_target *target)
{
const struct xt_led_info *led = (void *)target->data;
const char *id = led->id + strlen("netfilter-"); /* trim off prefix */
printf(" --led-trigger-id \"");
/* Escape double quotes and backslashes in the ID */
while (*id != '\0') {
if (*id == '"' || *id == '\\')
printf("\\");
printf("%c", *id++);
}
printf("\"");
/* Only print the delay if it's not zero (the default) */
if (led->delay > 0)
printf(" --led-delay %d", led->delay);
else if (led->delay == -1)
printf(" --led-delay inf");
/* Only print always_blink if it's not set to the default */
if (led->always_blink)
printf(" --led-always-blink");
}
static struct xtables_target led_tg_reg = {
.version = XTABLES_VERSION,
.name = "LED",
.family = PF_UNSPEC,
.revision = 0,
.size = XT_ALIGN(sizeof(struct xt_led_info)),
.userspacesize = offsetof(struct xt_led_info, internal_data),
.help = LED_help,
.print = LED_print,
.save = LED_save,
.x6_parse = LED_parse,
.x6_options = LED_opts,
};
void _init(void)
{
xtables_register_target(&led_tg_reg);
}
This creates an LED-trigger that can then be attached to system indicator
lights, to blink or illuminate them when certain packets pass through the
system. One example might be to light up an LED for a few minutes every time
an SSH connection is made to the local machine. The following options control
the trigger behavior:
.TP
\fB\-\-led\-trigger\-id\fP \fIname\fP
This is the name given to the LED trigger. The actual name of the trigger
will be prefixed with "netfilter-".
.TP
\fB\-\-led-delay\fP \fIms\fP
This indicates how long (in milliseconds) the LED should be left illuminated
when a packet arrives before being switched off again. The default is 0
(blink as fast as possible.) The special value \fIinf\fP can be given to
leave the LED on permanently once activated. (In this case the trigger will
need to be manually detached and reattached to the LED device to switch it
off again.)
.TP
\fB\-\-led\-always\-blink\fP
Always make the LED blink on packet arrival, even if the LED is already on.
This allows notification of new packets even with long delay values (which
otherwise would result in a silent prolonging of the delay time.)
.TP
Example:
.TP
Create an LED trigger for incoming SSH traffic:
iptables \-A INPUT \-p tcp \-\-dport 22 \-j LED \-\-led\-trigger\-id ssh
.TP
Then attach the new trigger to an LED:
echo netfilter\-ssh >/sys/class/leds/\fIledname\fP/trigger
Turn on kernel logging of matching packets. When this option is set
for a rule, the Linux kernel will print some information on all
matching packets (like most IP/IPv6 header fields) via the kernel log
(where it can be read with \fIdmesg(1)\fP or read in the syslog).
.PP
This is a "non-terminating target", i.e. rule traversal continues at
the next rule. So if you want to LOG the packets you refuse, use two
separate rules with the same matching criteria, first using target LOG
then DROP (or REJECT).
.TP
\fB\-\-log\-level\fP \fIlevel\fP
Level of logging, which can be (system-specific) numeric or a mnemonic.
Possible values are (in decreasing order of priority): \fBemerg\fP,
\fBalert\fP, \fBcrit\fP, \fBerror\fP, \fBwarning\fP, \fBnotice\fP, \fBinfo\fP
or \fBdebug\fP.
.TP
\fB\-\-log\-prefix\fP \fIprefix\fP
Prefix log messages with the specified prefix; up to 29 letters long,
and useful for distinguishing messages in the logs.
.TP
\fB\-\-log\-tcp\-sequence\fP
Log TCP sequence numbers. This is a security risk if the log is
readable by users.
.TP
\fB\-\-log\-tcp\-options\fP
Log options from the TCP packet header.
.TP
\fB\-\-log\-ip\-options\fP
Log options from the IP/IPv6 packet header.
.TP
\fB\-\-log\-uid\fP
Log the userid of the process which generated the packet.
#include <stdbool.h>
#include <stdio.h>
#include <xtables.h>
#include <linux/netfilter/xt_MARK.h>
/* Version 0 */
struct xt_mark_target_info {
unsigned long mark;
};
/* Version 1 */
enum {
XT_MARK_SET=0,
XT_MARK_AND,
XT_MARK_OR,
};
struct xt_mark_target_info_v1 {
unsigned long mark;
uint8_t mode;
};
enum {
O_SET_MARK = 0,
O_AND_MARK,
O_OR_MARK,
O_XOR_MARK,
O_SET_XMARK,
F_SET_MARK = 1 << O_SET_MARK,
F_AND_MARK = 1 << O_AND_MARK,
F_OR_MARK = 1 << O_OR_MARK,
F_XOR_MARK = 1 << O_XOR_MARK,
F_SET_XMARK = 1 << O_SET_XMARK,
F_ANY = F_SET_MARK | F_AND_MARK | F_OR_MARK |
F_XOR_MARK | F_SET_XMARK,
};
static void MARK_help(void)
{
printf(
"MARK target options:\n"
" --set-mark value Set nfmark value\n"
" --and-mark value Binary AND the nfmark with value\n"
" --or-mark value Binary OR the nfmark with value\n");
}
static const struct xt_option_entry MARK_opts[] = {
{.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_UINT32,
.excl = F_ANY},
{.name = "and-mark", .id = O_AND_MARK, .type = XTTYPE_UINT32,
.excl = F_ANY},
{.name = "or-mark", .id = O_OR_MARK, .type = XTTYPE_UINT32,
.excl = F_ANY},
XTOPT_TABLEEND,
};
static const struct xt_option_entry mark_tg_opts[] = {
{.name = "set-xmark", .id = O_SET_XMARK, .type = XTTYPE_MARKMASK32,
.excl = F_ANY},
{.name = "set-mark", .id = O_SET_MARK, .type = XTTYPE_MARKMASK32,
.excl = F_ANY},
{.name = "and-mark", .id = O_AND_MARK, .type = XTTYPE_UINT32,
.excl = F_ANY},
{.name = "or-mark", .id = O_OR_MARK, .type = XTTYPE_UINT32,
.excl = F_ANY},
{.name = "xor-mark", .id = O_XOR_MARK, .type = XTTYPE_UINT32,
.excl = F_ANY},
XTOPT_TABLEEND,
};
static void mark_tg_help(void)
{
printf(
"MARK target options:\n"
" --set-xmark value[/mask] Clear bits in mask and XOR value into nfmark\n"
" --set-mark value[/mask] Clear bits in mask and OR value into nfmark\n"
" --and-mark bits Binary AND the nfmark with bits\n"
" --or-mark bits Binary OR the nfmark with bits\n"
" --xor-mask bits Binary XOR the nfmark with bits\n"
"\n");
}
static void MARK_parse_v0(struct xt_option_call *cb)
{
struct xt_mark_target_info *markinfo = cb->data;
xtables_option_parse(cb);
switch (cb->entry->id) {
case O_SET_MARK:
markinfo->mark = cb->val.mark;
break;
default:
xtables_error(PARAMETER_PROBLEM,
"MARK target: kernel too old for --%s",
cb->entry->name);
}
}
static void MARK_check(struct xt_fcheck_call *cb)
{
if (cb->xflags == 0)
xtables_error(PARAMETER_PROBLEM,
"MARK target: Parameter --set/and/or-mark"
" is required");
}
static void MARK_parse_v1(struct xt_option_call *cb)
{
struct xt_mark_target_info_v1 *markinfo = cb->data;
xtables_option_parse(cb);
switch (cb->entry->id) {
case O_SET_MARK:
markinfo->mode = XT_MARK_SET;
break;
case O_AND_MARK:
markinfo->mode = XT_MARK_AND;
break;
case O_OR_MARK:
markinfo->mode = XT_MARK_OR;
break;
}
markinfo->mark = cb->val.u32;
}
static void mark_tg_parse(struct xt_option_call *cb)
{
struct xt_mark_tginfo2 *info = cb->data;
xtables_option_parse(cb);
switch (cb->entry->id) {
case O_SET_XMARK:
info->mark = cb->val.mark;
info->mask = cb->val.mask;
break;
case O_SET_MARK:
info->mark = cb->val.mark;
info->mask = cb->val.mark | cb->val.mask;
break;
case O_AND_MARK:
info->mark = 0;
info->mask = ~cb->val.u32;
break;
case O_OR_MARK:
info->mark = info->mask = cb->val.u32;
break;
case O_XOR_MARK:
info->mark = cb->val.u32;
info->mask = 0;
break;
}
}
static void mark_tg_check(struct xt_fcheck_call *cb)
{
if (cb->xflags == 0)
xtables_error(PARAMETER_PROBLEM, "MARK: One of the --set-xmark, "
"--{and,or,xor,set}-mark options is required");
}
static void
print_mark(unsigned long mark)
{
printf(" 0x%lx", mark);
}
static void MARK_print_v0(const void *ip,
const struct xt_entry_target *target, int numeric)
{
const struct xt_mark_target_info *markinfo =
(const struct xt_mark_target_info *)target->data;
printf(" MARK set");
print_mark(markinfo->mark);
}
static void MARK_save_v0(const void *ip, const struct xt_entry_target *target)
{
const struct xt_mark_target_info *markinfo =
(const struct xt_mark_target_info *)target->data;
printf(" --set-mark");
print_mark(markinfo->mark);
}
static void MARK_print_v1(const void *ip, const struct xt_entry_target *target,
int numeric)
{
const struct xt_mark_target_info_v1 *markinfo =
(const struct xt_mark_target_info_v1 *)target->data;
switch (markinfo->mode) {
case XT_MARK_SET:
printf(" MARK set");
break;
case XT_MARK_AND:
printf(" MARK and");
break;
case XT_MARK_OR:
printf(" MARK or");
break;
}
print_mark(markinfo->mark);
}
static void mark_tg_print(const void *ip, const struct xt_entry_target *target,
int numeric)
{
const struct xt_mark_tginfo2 *info = (const void *)target->data;
if (info->mark == 0)
printf(" MARK and 0x%x", (unsigned int)(uint32_t)~info->mask);
else if (info->mark == info->mask)
printf(" MARK or 0x%x", info->mark);
else if (info->mask == 0)
printf(" MARK xor 0x%x", info->mark);
else if (info->mask == 0xffffffffU)
printf(" MARK set 0x%x", info->mark);
else
printf(" MARK xset 0x%x/0x%x", info->mark, info->mask);
}
static void MARK_save_v1(const void *ip, const struct xt_entry_target *target)
{
const struct xt_mark_target_info_v1 *markinfo =
(const struct xt_mark_target_info_v1 *)target->data;
switch (markinfo->mode) {
case XT_MARK_SET:
printf(" --set-mark");
break;
case XT_MARK_AND:
printf(" --and-mark");
break;
case XT_MARK_OR:
printf(" --or-mark");
break;
}
print_mark(markinfo->mark);
}
static void mark_tg_save(const void *ip, const struct xt_entry_target *target)
{
const struct xt_mark_tginfo2 *info = (const void *)target->data;
printf(" --set-xmark 0x%x/0x%x", info->mark, info->mask);
}
static struct xtables_target mark_tg_reg[] = {
{
.family = NFPROTO_UNSPEC,
.name = "MARK",
.version = XTABLES_VERSION,
.revision = 0,
.size = XT_ALIGN(sizeof(struct xt_mark_target_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_mark_target_info)),
.help = MARK_help,
.print = MARK_print_v0,
.save = MARK_save_v0,
.x6_parse = MARK_parse_v0,
.x6_fcheck = MARK_check,
.x6_options = MARK_opts,
},
{
.family = NFPROTO_IPV4,
.name = "MARK",
.version = XTABLES_VERSION,
.revision = 1,
.size = XT_ALIGN(sizeof(struct xt_mark_target_info_v1)),
.userspacesize = XT_ALIGN(sizeof(struct xt_mark_target_info_v1)),
.help = MARK_help,
.print = MARK_print_v1,
.save = MARK_save_v1,
.x6_parse = MARK_parse_v1,
.x6_fcheck = MARK_check,
.x6_options = MARK_opts,
},
{
.version = XTABLES_VERSION,
.name = "MARK",
.revision = 2,
.family = NFPROTO_UNSPEC,
.size = XT_ALIGN(sizeof(struct xt_mark_tginfo2)),
.userspacesize = XT_ALIGN(sizeof(struct xt_mark_tginfo2)),
.help = mark_tg_help,
.print = mark_tg_print,
.save = mark_tg_save,
.x6_parse = mark_tg_parse,
.x6_fcheck = mark_tg_check,
.x6_options = mark_tg_opts,
},
};
void _init(void)
{
xtables_register_targets(mark_tg_reg, ARRAY_SIZE(mark_tg_reg));
}
This target is used to set the Netfilter mark value associated with the packet.
It can, for example, be used in conjunction with routing based on fwmark (needs
iproute2). If you plan on doing so, note that the mark needs to be set in the
PREROUTING chain of the mangle table to affect routing.
The mark field is 32 bits wide.
.TP
\fB\-\-set\-xmark\fP \fIvalue\fP[\fB/\fP\fImask\fP]
Zeroes out the bits given by \fImask\fP and XORs \fIvalue\fP into the packet
mark ("nfmark"). If \fImask\fP is omitted, 0xFFFFFFFF is assumed.
.TP
\fB\-\-set\-mark\fP \fIvalue\fP[\fB/\fP\fImask\fP]
Zeroes out the bits given by \fImask\fP and ORs \fIvalue\fP into the packet
mark. If \fImask\fP is omitted, 0xFFFFFFFF is assumed.
.PP
The following mnemonics are available:
.TP
\fB\-\-and\-mark\fP \fIbits\fP
Binary AND the nfmark with \fIbits\fP. (Mnemonic for \fB\-\-set\-xmark
0/\fP\fIinvbits\fP, where \fIinvbits\fP is the binary negation of \fIbits\fP.)
.TP
\fB\-\-or\-mark\fP \fIbits\fP
Binary OR the nfmark with \fIbits\fP. (Mnemonic for \fB\-\-set\-xmark\fP
\fIbits\fP\fB/\fP\fIbits\fP.)
.TP
\fB\-\-xor\-mark\fP \fIbits\fP
Binary XOR the nfmark with \fIbits\fP. (Mnemonic for \fB\-\-set\-xmark\fP
\fIbits\fP\fB/0\fP.)
This target is only valid in the
.B nat
table, in the
.B POSTROUTING
chain. It should only be used with dynamically assigned IP (dialup)
connections: if you have a static IP address, you should use the SNAT
target. Masquerading is equivalent to specifying a mapping to the IP
address of the interface the packet is going out, but also has the
effect that connections are
.I forgotten
when the interface goes down. This is the correct behavior when the
next dialup is unlikely to have the same interface address (and hence
any established connections are lost anyway).
.TP
\fB\-\-to\-ports\fP \fIport\fP[\fB\-\fP\fIport\fP]
This specifies a range of source ports to use, overriding the default
.B SNAT
source port-selection heuristics (see above). This is only valid
if the rule also specifies one of the following protocols:
\fBtcp\fP, \fBudp\fP, \fBdccp\fP or \fBsctp\fP.
.TP
\fB\-\-random\fP
Randomize source port mapping
If option
\fB\-\-random\fP
is used then port mapping will be randomized (kernel >= 2.6.21).
.TP
IPv6 support available since Linux kernels >= 3.7.
This target allows you to statically map a whole network of addresses onto
another network of addresses. It can only be used from rules in the
.B nat
table.
.TP
\fB\-\-to\fP \fIaddress\fP[\fB/\fP\fImask\fP]
Network address to map to. The resulting address will be constructed in the
following way: All 'one' bits in the mask are filled in from the new `address'.
All bits that are zero in the mask are filled in from the original address.
.TP
IPv6 support available since Linux kernels >= 3.7.
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <getopt.h>
#include <xtables.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_NFLOG.h>
enum {
O_GROUP = 0,
O_PREFIX,
O_RANGE,
O_THRESHOLD,
};
#define s struct xt_nflog_info
static const struct xt_option_entry NFLOG_opts[] = {
{.name = "nflog-group", .id = O_GROUP, .type = XTTYPE_UINT16,
.flags = XTOPT_PUT, XTOPT_POINTER(s, group)},
{.name = "nflog-prefix", .id = O_PREFIX, .type = XTTYPE_STRING,
.min = 1, .flags = XTOPT_PUT, XTOPT_POINTER(s, prefix)},
{.name = "nflog-range", .id = O_RANGE, .type = XTTYPE_UINT32,
.flags = XTOPT_PUT, XTOPT_POINTER(s, len)},
{.name = "nflog-threshold", .id = O_THRESHOLD, .type = XTTYPE_UINT16,
.flags = XTOPT_PUT, XTOPT_POINTER(s, threshold)},
XTOPT_TABLEEND,
};
#undef s
static void NFLOG_help(void)
{
printf("NFLOG target options:\n"
" --nflog-group NUM NETLINK group used for logging\n"
" --nflog-range NUM Number of byte to copy\n"
" --nflog-threshold NUM Message threshold of in-kernel queue\n"
" --nflog-prefix STRING Prefix string for log messages\n");
}
static void NFLOG_init(struct xt_entry_target *t)
{
struct xt_nflog_info *info = (struct xt_nflog_info *)t->data;
info->threshold = XT_NFLOG_DEFAULT_THRESHOLD;
}
static void NFLOG_parse(struct xt_option_call *cb)
{
xtables_option_parse(cb);
switch (cb->entry->id) {
case O_PREFIX:
if (strchr(cb->arg, '\n') != NULL)
xtables_error(PARAMETER_PROBLEM,
"Newlines not allowed in --log-prefix");
break;
}
}
static void nflog_print(const struct xt_nflog_info *info, char *prefix)
{
if (info->prefix[0] != '\0') {
printf(" %snflog-prefix ", prefix);
xtables_save_string(info->prefix);
}
if (info->group)
printf(" %snflog-group %u", prefix, info->group);
if (info->len)
printf(" %snflog-range %u", prefix, info->len);
if (info->threshold != XT_NFLOG_DEFAULT_THRESHOLD)
printf(" %snflog-threshold %u", prefix, info->threshold);
}
static void NFLOG_print(const void *ip, const struct xt_entry_target *target,
int numeric)
{
const struct xt_nflog_info *info = (struct xt_nflog_info *)target->data;
nflog_print(info, "");
}
static void NFLOG_save(const void *ip, const struct xt_entry_target *target)
{
const struct xt_nflog_info *info = (struct xt_nflog_info *)target->data;
nflog_print(info, "--");
}
static struct xtables_target nflog_target = {
.family = NFPROTO_UNSPEC,
.name = "NFLOG",
.version = XTABLES_VERSION,
.size = XT_ALIGN(sizeof(struct xt_nflog_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_nflog_info)),
.help = NFLOG_help,
.init = NFLOG_init,
.x6_parse = NFLOG_parse,
.print = NFLOG_print,
.save = NFLOG_save,
.x6_options = NFLOG_opts,
};
void _init(void)
{
xtables_register_target(&nflog_target);
}
This target provides logging of matching packets. When this target is
set for a rule, the Linux kernel will pass the packet to the loaded
logging backend to log the packet. This is usually used in combination
with nfnetlink_log as logging backend, which will multicast the packet
through a
.IR netlink
socket to the specified multicast group. One or more userspace processes
may subscribe to the group to receive the packets. Like LOG, this is a
non-terminating target, i.e. rule traversal continues at the next rule.
.TP
\fB\-\-nflog\-group\fP \fInlgroup\fP
The netlink group (0 - 2^16\-1) to which packets are (only applicable for
nfnetlink_log). The default value is 0.
.TP
\fB\-\-nflog\-prefix\fP \fIprefix\fP
A prefix string to include in the log message, up to 64 characters
long, useful for distinguishing messages in the logs.
.TP
\fB\-\-nflog\-range\fP \fIsize\fP
The number of bytes to be copied to userspace (only applicable for
nfnetlink_log). nfnetlink_log instances may specify their own
range, this option overrides it.
.TP
\fB\-\-nflog\-threshold\fP \fIsize\fP
Number of packets to queue inside the kernel before sending them
to userspace (only applicable for nfnetlink_log). Higher values
result in less overhead per packet, but increase delay until the
packets reach userspace. The default value is 1.
.BR
/* Shared library add-on to iptables for NFQ
*
* (C) 2005 by Harald Welte <laforge@netfilter.org>
*
* This program is distributed under the terms of GNU GPL v2, 1991
*
*/
#include <stdio.h>
#include <xtables.h>
#include <linux/netfilter/xt_NFQUEUE.h>
enum {
O_QUEUE_NUM = 0,
O_QUEUE_BALANCE,
O_QUEUE_BYPASS,
O_QUEUE_CPU_FANOUT,
F_QUEUE_NUM = 1 << O_QUEUE_NUM,
F_QUEUE_BALANCE = 1 << O_QUEUE_BALANCE,
F_QUEUE_CPU_FANOUT = 1 << O_QUEUE_CPU_FANOUT,
};
static void NFQUEUE_help(void)
{
printf(
"NFQUEUE target options\n"
" --queue-num value Send packet to QUEUE number <value>.\n"
" Valid queue numbers are 0-65535\n"
);
}
static void NFQUEUE_help_v1(void)
{
NFQUEUE_help();
printf(
" --queue-balance first:last Balance flows between queues <value> to <value>.\n");
}
static void NFQUEUE_help_v2(void)
{
NFQUEUE_help_v1();
printf(
" --queue-bypass Bypass Queueing if no queue instance exists.\n"
" --queue-cpu-fanout Use current CPU (no hashing)\n");
}
static void NFQUEUE_help_v3(void)
{
NFQUEUE_help_v2();
printf(
" --queue-cpu-fanout Use current CPU (no hashing)\n");
}
#define s struct xt_NFQ_info
static const struct xt_option_entry NFQUEUE_opts[] = {
{.name = "queue-num", .id = O_QUEUE_NUM, .type = XTTYPE_UINT16,
.flags = XTOPT_PUT, XTOPT_POINTER(s, queuenum),
.excl = F_QUEUE_BALANCE},
{.name = "queue-balance", .id = O_QUEUE_BALANCE,
.type = XTTYPE_UINT16RC, .excl = F_QUEUE_NUM},
{.name = "queue-bypass", .id = O_QUEUE_BYPASS, .type = XTTYPE_NONE},
{.name = "queue-cpu-fanout", .id = O_QUEUE_CPU_FANOUT,
.type = XTTYPE_NONE, .also = F_QUEUE_BALANCE},
XTOPT_TABLEEND,
};
#undef s
static void NFQUEUE_parse(struct xt_option_call *cb)
{
xtables_option_parse(cb);
if (cb->entry->id == O_QUEUE_BALANCE)
xtables_error(PARAMETER_PROBLEM, "NFQUEUE target: "
"--queue-balance not supported (kernel too old?)");
}
static void NFQUEUE_parse_v1(struct xt_option_call *cb)
{
struct xt_NFQ_info_v1 *info = cb->data;
const uint16_t *r = cb->val.u16_range;
xtables_option_parse(cb);
switch (cb->entry->id) {
case O_QUEUE_BALANCE:
if (cb->nvals != 2)
xtables_error(PARAMETER_PROBLEM,
"Bad range \"%s\"", cb->arg);
if (r[0] >= r[1])
xtables_error(PARAMETER_PROBLEM, "%u should be less than %u",
r[0], r[1]);
info->queuenum = r[0];
info->queues_total = r[1] - r[0] + 1;
break;
}
}
static void NFQUEUE_parse_v2(struct xt_option_call *cb)
{
struct xt_NFQ_info_v2 *info = cb->data;
NFQUEUE_parse_v1(cb);
switch (cb->entry->id) {
case O_QUEUE_BYPASS:
info->bypass = 1;
break;
}
}
static void NFQUEUE_parse_v3(struct xt_option_call *cb)
{
struct xt_NFQ_info_v3 *info = cb->data;
NFQUEUE_parse_v2(cb);
switch (cb->entry->id) {
case O_QUEUE_CPU_FANOUT:
info->flags |= NFQ_FLAG_CPU_FANOUT;
break;
}
}
static void NFQUEUE_print(const void *ip,
const struct xt_entry_target *target, int numeric)
{
const struct xt_NFQ_info *tinfo =
(const struct xt_NFQ_info *)target->data;
printf(" NFQUEUE num %u", tinfo->queuenum);
}
static void NFQUEUE_print_v1(const void *ip,
const struct xt_entry_target *target, int numeric)
{
const struct xt_NFQ_info_v1 *tinfo = (const void *)target->data;
unsigned int last = tinfo->queues_total;
if (last > 1) {
last += tinfo->queuenum - 1;
printf(" NFQUEUE balance %u:%u", tinfo->queuenum, last);
} else {
printf(" NFQUEUE num %u", tinfo->queuenum);
}
}
static void NFQUEUE_print_v2(const void *ip,
const struct xt_entry_target *target, int numeric)
{
const struct xt_NFQ_info_v2 *info = (void *) target->data;
NFQUEUE_print_v1(ip, target, numeric);
if (info->bypass & NFQ_FLAG_BYPASS)
printf(" bypass");
}
static void NFQUEUE_print_v3(const void *ip,
const struct xt_entry_target *target, int numeric)
{
const struct xt_NFQ_info_v3 *info = (void *)target->data;
NFQUEUE_print_v2(ip, target, numeric);
if (info->flags & NFQ_FLAG_CPU_FANOUT)
printf(" cpu-fanout");
}
static void NFQUEUE_save(const void *ip, const struct xt_entry_target *target)
{
const struct xt_NFQ_info *tinfo =
(const struct xt_NFQ_info *)target->data;
printf(" --queue-num %u", tinfo->queuenum);
}
static void NFQUEUE_save_v1(const void *ip, const struct xt_entry_target *target)
{
const struct xt_NFQ_info_v1 *tinfo = (const void *)target->data;
unsigned int last = tinfo->queues_total;
if (last > 1) {
last += tinfo->queuenum - 1;
printf(" --queue-balance %u:%u", tinfo->queuenum, last);
} else {
printf(" --queue-num %u", tinfo->queuenum);
}
}
static void NFQUEUE_save_v2(const void *ip, const struct xt_entry_target *target)
{
const struct xt_NFQ_info_v2 *info = (void *) target->data;
NFQUEUE_save_v1(ip, target);
if (info->bypass & NFQ_FLAG_BYPASS)
printf(" --queue-bypass");
}
static void NFQUEUE_save_v3(const void *ip,
const struct xt_entry_target *target)
{
const struct xt_NFQ_info_v3 *info = (void *)target->data;
NFQUEUE_save_v2(ip, target);
if (info->flags & NFQ_FLAG_CPU_FANOUT)
printf(" --queue-cpu-fanout");
}
static void NFQUEUE_init_v1(struct xt_entry_target *t)
{
struct xt_NFQ_info_v1 *tinfo = (void *)t->data;
tinfo->queues_total = 1;
}
static struct xtables_target nfqueue_targets[] = {
{
.family = NFPROTO_UNSPEC,
.name = "NFQUEUE",
.version = XTABLES_VERSION,
.size = XT_ALIGN(sizeof(struct xt_NFQ_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info)),
.help = NFQUEUE_help,
.print = NFQUEUE_print,
.save = NFQUEUE_save,
.x6_parse = NFQUEUE_parse,
.x6_options = NFQUEUE_opts
},{
.family = NFPROTO_UNSPEC,
.revision = 1,
.name = "NFQUEUE",
.version = XTABLES_VERSION,
.size = XT_ALIGN(sizeof(struct xt_NFQ_info_v1)),
.userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info_v1)),
.help = NFQUEUE_help_v1,
.init = NFQUEUE_init_v1,
.print = NFQUEUE_print_v1,
.save = NFQUEUE_save_v1,
.x6_parse = NFQUEUE_parse_v1,
.x6_options = NFQUEUE_opts,
},{
.family = NFPROTO_UNSPEC,
.revision = 2,
.name = "NFQUEUE",
.version = XTABLES_VERSION,
.size = XT_ALIGN(sizeof(struct xt_NFQ_info_v2)),
.userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info_v2)),
.help = NFQUEUE_help_v2,
.init = NFQUEUE_init_v1,
.print = NFQUEUE_print_v2,
.save = NFQUEUE_save_v2,
.x6_parse = NFQUEUE_parse_v2,
.x6_options = NFQUEUE_opts,
},{
.family = NFPROTO_UNSPEC,
.revision = 3,
.name = "NFQUEUE",
.version = XTABLES_VERSION,
.size = XT_ALIGN(sizeof(struct xt_NFQ_info_v3)),
.userspacesize = XT_ALIGN(sizeof(struct xt_NFQ_info_v3)),
.help = NFQUEUE_help_v3,
.init = NFQUEUE_init_v1,
.print = NFQUEUE_print_v3,
.save = NFQUEUE_save_v3,
.x6_parse = NFQUEUE_parse_v3,
.x6_options = NFQUEUE_opts,
}
};
void _init(void)
{
xtables_register_targets(nfqueue_targets, ARRAY_SIZE(nfqueue_targets));
}
This target passes the packet to userspace using the
\fBnfnetlink_queue\fP handler. The packet is put into the queue
identified by its 16-bit queue number. Userspace can inspect
and modify the packet if desired. Userspace must then drop or
reinject the packet into the kernel. Please see libnetfilter_queue
for details.
.B
nfnetlink_queue
was added in Linux 2.6.14. The \fBqueue-balance\fP option was added in Linux 2.6.31,
\fBqueue-bypass\fP in 2.6.39.
.TP
\fB\-\-queue\-num\fP \fIvalue\fP
This specifies the QUEUE number to use. Valid queue numbers are 0 to 65535. The default value is 0.
.PP
.TP
\fB\-\-queue\-balance\fP \fIvalue\fP\fB:\fP\fIvalue\fP
This specifies a range of queues to use. Packets are then balanced across the given queues.
This is useful for multicore systems: start multiple instances of the userspace program on
queues x, x+1, .. x+n and use "\-\-queue\-balance \fIx\fP\fB:\fP\fIx+n\fP".
Packets belonging to the same connection are put into the same nfqueue.
.PP
.TP
\fB\-\-queue\-bypass\fP
By default, if no userspace program is listening on an NFQUEUE, then all packets that are to be queued
are dropped. When this option is used, the NFQUEUE rule behaves like ACCEPT instead, and the packet
will move on to the next table.
.PP
.TP
\fB\-\-queue\-cpu-fanout\fP
Available starting Linux kernel 3.10. When used together with
\fB--queue-balance\fP this will use the CPU ID as an index to map packets to
the queues. The idea is that you can improve performance if there's a queue
per CPU. This requires \fB--queue-balance\fP to be specified.
This extension disables connection tracking for all packets matching that rule.
It is equivalent with \-j CT \-\-notrack. Like CT, NOTRACK can only be used in
the \fBraw\fP table.
/*
* Copyright (c) 2008-2013 Patrick McHardy <kaber@trash.net>
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <xtables.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_RATEEST.h>
struct rateest_tg_udata {
unsigned int interval;
unsigned int ewma_log;
};
static void
RATEEST_help(void)
{
printf(
"RATEEST target options:\n"
" --rateest-name name Rate estimator name\n"
" --rateest-interval sec Rate measurement interval in seconds\n"
" --rateest-ewmalog value Rate measurement averaging time constant\n");
}
enum {
O_NAME = 0,
O_INTERVAL,
O_EWMALOG,
};
#define s struct xt_rateest_target_info
static const struct xt_option_entry RATEEST_opts[] = {
{.name = "rateest-name", .id = O_NAME, .type = XTTYPE_STRING,
.flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, name)},
{.name = "rateest-interval", .id = O_INTERVAL, .type = XTTYPE_STRING,
.flags = XTOPT_MAND},
{.name = "rateest-ewmalog", .id = O_EWMALOG, .type = XTTYPE_STRING,
.flags = XTOPT_MAND},
XTOPT_TABLEEND,
};
#undef s
/* Copied from iproute */
#define TIME_UNITS_PER_SEC 1000000
static int
RATEEST_get_time(unsigned int *time, const char *str)
{
double t;
char *p;
t = strtod(str, &p);
if (p == str)
return -1;
if (*p) {
if (strcasecmp(p, "s") == 0 || strcasecmp(p, "sec")==0 ||
strcasecmp(p, "secs")==0)
t *= TIME_UNITS_PER_SEC;
else if (strcasecmp(p, "ms") == 0 || strcasecmp(p, "msec")==0 ||
strcasecmp(p, "msecs") == 0)
t *= TIME_UNITS_PER_SEC/1000;
else if (strcasecmp(p, "us") == 0 || strcasecmp(p, "usec")==0 ||
strcasecmp(p, "usecs") == 0)
t *= TIME_UNITS_PER_SEC/1000000;
else
return -1;
}
*time = t;
return 0;
}
static void
RATEEST_print_time(unsigned int time)
{
double tmp = time;
if (tmp >= TIME_UNITS_PER_SEC)
printf(" %.1fs", tmp / TIME_UNITS_PER_SEC);
else if (tmp >= TIME_UNITS_PER_SEC/1000)
printf(" %.1fms", tmp / (TIME_UNITS_PER_SEC / 1000));
else
printf(" %uus", time);
}
static void RATEEST_parse(struct xt_option_call *cb)
{
struct rateest_tg_udata *udata = cb->udata;
xtables_option_parse(cb);
switch (cb->entry->id) {
case O_INTERVAL:
if (RATEEST_get_time(&udata->interval, cb->arg) < 0)
xtables_error(PARAMETER_PROBLEM,
"RATEEST: bad interval value \"%s\"",
cb->arg);
break;
case O_EWMALOG:
if (RATEEST_get_time(&udata->ewma_log, cb->arg) < 0)
xtables_error(PARAMETER_PROBLEM,
"RATEEST: bad ewmalog value \"%s\"",
cb->arg);
break;
}
}
static void RATEEST_final_check(struct xt_fcheck_call *cb)
{
struct xt_rateest_target_info *info = cb->data;
struct rateest_tg_udata *udata = cb->udata;
for (info->interval = 0; info->interval <= 5; info->interval++) {
if (udata->interval <= (1 << info->interval) * (TIME_UNITS_PER_SEC / 4))
break;
}
if (info->interval > 5)
xtables_error(PARAMETER_PROBLEM,
"RATEEST: interval value is too large");
info->interval -= 2;
for (info->ewma_log = 1; info->ewma_log < 32; info->ewma_log++) {
double w = 1.0 - 1.0 / (1 << info->ewma_log);
if (udata->interval / (-log(w)) > udata->ewma_log)
break;
}
info->ewma_log--;
if (info->ewma_log == 0 || info->ewma_log >= 31)
xtables_error(PARAMETER_PROBLEM,
"RATEEST: ewmalog value is out of range");
}
static void
__RATEEST_print(const struct xt_entry_target *target, const char *prefix)
{
const struct xt_rateest_target_info *info = (const void *)target->data;
unsigned int local_interval;
unsigned int local_ewma_log;
local_interval = (TIME_UNITS_PER_SEC << (info->interval + 2)) / 4;
local_ewma_log = local_interval * (1 << (info->ewma_log));
printf(" %sname %s", prefix, info->name);
printf(" %sinterval", prefix);
RATEEST_print_time(local_interval);
printf(" %sewmalog", prefix);
RATEEST_print_time(local_ewma_log);
}
static void
RATEEST_print(const void *ip, const struct xt_entry_target *target,
int numeric)
{
__RATEEST_print(target, "");
}
static void
RATEEST_save(const void *ip, const struct xt_entry_target *target)
{
__RATEEST_print(target, "--rateest-");
}
static struct xtables_target rateest_tg_reg = {
.family = NFPROTO_UNSPEC,
.name = "RATEEST",
.version = XTABLES_VERSION,
.size = XT_ALIGN(sizeof(struct xt_rateest_target_info)),
.userspacesize = offsetof(struct xt_rateest_target_info, est),
.help = RATEEST_help,
.x6_parse = RATEEST_parse,
.x6_fcheck = RATEEST_final_check,
.print = RATEEST_print,
.save = RATEEST_save,
.x6_options = RATEEST_opts,
.udata_size = sizeof(struct rateest_tg_udata),
};
void _init(void)
{
xtables_register_target(&rateest_tg_reg);
}
The RATEEST target collects statistics, performs rate estimation calculation
and saves the results for later evaluation using the \fBrateest\fP match.
.TP
\fB\-\-rateest\-name\fP \fIname\fP
Count matched packets into the pool referred to by \fIname\fP, which is freely
choosable.
.TP
\fB\-\-rateest\-interval\fP \fIamount\fP{\fBs\fP|\fBms\fP|\fBus\fP}
Rate measurement interval, in seconds, milliseconds or microseconds.
.TP
\fB\-\-rateest\-ewmalog\fP \fIvalue\fP
Rate measurement averaging time constant.
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment