Commit 615f9fca authored by Arturo Borrero Gonzalez's avatar Arturo Borrero Gonzalez
Browse files

Imported Upstream version 1.6.0

parent 7e95a8db
......@@ -11,10 +11,12 @@
enum {
O_TO_SRC = 0,
O_RANDOM,
O_RANDOM_FULLY,
O_PERSISTENT,
O_X_TO_SRC,
F_TO_SRC = 1 << O_TO_SRC,
F_RANDOM = 1 << O_RANDOM,
F_RANDOM_FULLY = 1 << O_RANDOM_FULLY,
F_X_TO_SRC = 1 << O_X_TO_SRC,
};
......@@ -32,13 +34,14 @@ static void SNAT_help(void)
"SNAT target options:\n"
" --to-source [<ipaddr>[-<ipaddr>]][:port[-port]]\n"
" Address to map source to.\n"
"[--random] [--persistent]\n");
"[--random] [--random-fully] [--persistent]\n");
}
static const struct xt_option_entry SNAT_opts[] = {
{.name = "to-source", .id = O_TO_SRC, .type = XTTYPE_STRING,
.flags = XTOPT_MAND | XTOPT_MULTI},
{.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
{.name = "random-fully", .id = O_RANDOM_FULLY, .type = XTTYPE_NONE},
{.name = "persistent", .id = O_PERSISTENT, .type = XTTYPE_NONE},
XTOPT_TABLEEND,
};
......@@ -185,10 +188,13 @@ static void SNAT_parse(struct xt_option_call *cb)
static void SNAT_fcheck(struct xt_fcheck_call *cb)
{
static const unsigned int f = F_TO_SRC | F_RANDOM;
static const unsigned int r = F_TO_SRC | F_RANDOM_FULLY;
struct nf_nat_ipv4_multi_range_compat *mr = cb->data;
if ((cb->xflags & f) == f)
mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM;
if ((cb->xflags & r) == r)
mr->range[0].flags |= NF_NAT_RANGE_PROTO_RANDOM_FULLY;
}
static void print_range(const struct nf_nat_ipv4_range *r)
......@@ -222,6 +228,8 @@ static void SNAT_print(const void *ip, const struct xt_entry_target *target,
print_range(&info->mr.range[i]);
if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM)
printf(" random");
if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
printf(" random-fully");
if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT)
printf(" persistent");
}
......@@ -237,6 +245,8 @@ static void SNAT_save(const void *ip, const struct xt_entry_target *target)
print_range(&info->mr.range[i]);
if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM)
printf(" --random");
if (info->mr.range[i].flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
printf(" --random-fully");
if (info->mr.range[i].flags & NF_NAT_RANGE_PERSISTENT)
printf(" --persistent");
}
......
......@@ -21,6 +21,13 @@ static const struct xt_option_entry ah_opts[] = {
XTOPT_TABLEEND,
};
static void ah_init(struct xt_entry_match *m)
{
struct ipt_ah *ahinfo = (void *)m->data;
ahinfo->spis[1] = ~0U;
}
static void ah_parse(struct xt_option_call *cb)
{
struct ipt_ah *ahinfo = cb->data;
......@@ -92,6 +99,7 @@ static struct xtables_match ah_mt_reg = {
.size = XT_ALIGN(sizeof(struct ipt_ah)),
.userspacesize = XT_ALIGN(sizeof(struct ipt_ah)),
.help = ah_help,
.init = ah_init,
.print = ah_print,
.save = ah_save,
.x6_parse = ah_parse,
......
/* Shared library add-on to iptables for unclean. */
#include <xtables.h>
static struct xtables_match unclean_mt_reg = {
.name = "unclean",
.version = XTABLES_VERSION,
.family = NFPROTO_IPV4,
.size = XT_ALIGN(0),
.userspacesize = XT_ALIGN(0),
};
void _init(void)
{
xtables_register_match(&unclean_mt_reg);
}
This module takes no options, but attempts to match packets which seem
malformed or unusual. This is regarded as experimental.
......@@ -73,7 +73,15 @@ CLASSIFY_save(const void *ip, const struct xt_entry_target *target)
TC_H_MAJ(clinfo->priority)>>16, TC_H_MIN(clinfo->priority));
}
static struct xtables_target classify_target = {
static void
arpCLASSIFY_print(const void *ip, const struct xt_entry_target *target,
int numeric)
{
CLASSIFY_save(ip, target);
}
static struct xtables_target classify_target[] = {
{
.family = NFPROTO_UNSPEC,
.name = "CLASSIFY",
.version = XTABLES_VERSION,
......@@ -84,9 +92,21 @@ static struct xtables_target classify_target = {
.save = CLASSIFY_save,
.x6_parse = CLASSIFY_parse,
.x6_options = CLASSIFY_opts,
},
{
.family = NFPROTO_ARP,
.name = "CLASSIFY",
.version = XTABLES_VERSION,
.size = XT_ALIGN(sizeof(struct xt_classify_target_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_classify_target_info)),
.help = CLASSIFY_help,
.print = arpCLASSIFY_print,
.x6_parse = CLASSIFY_parse,
.x6_options = CLASSIFY_opts,
},
};
void _init(void)
{
xtables_register_target(&classify_target);
xtables_register_targets(classify_target, ARRAY_SIZE(classify_target));
}
......@@ -17,7 +17,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <stdbool.h>
#include <stdint.h>
......
......@@ -16,7 +16,9 @@ static void ct_help(void)
" --helper name Use conntrack helper 'name' for connection\n"
" --ctevents event[,event...] Generate specified conntrack events for connection\n"
" --expevents event[,event...] Generate specified expectation events for connection\n"
" --zone ID Assign/Lookup connection in zone ID\n"
" --zone {ID|mark} Assign/Lookup connection in zone ID/packet nfmark\n"
" --zone-orig {ID|mark} Same as 'zone' option, but only applies to ORIGINAL direction\n"
" --zone-reply {ID|mark} Same as 'zone' option, but only applies to REPLY direction\n"
);
}
......@@ -29,7 +31,9 @@ static void ct_help_v1(void)
" --timeout name Use timeout policy 'name' for connection\n"
" --ctevents event[,event...] Generate specified conntrack events for connection\n"
" --expevents event[,event...] Generate specified expectation events for connection\n"
" --zone ID Assign/Lookup connection in zone ID\n"
" --zone {ID|mark} Assign/Lookup connection in zone ID/packet nfmark\n"
" --zone-orig {ID|mark} Same as 'zone' option, but only applies to ORIGINAL direction\n"
" --zone-reply {ID|mark} Same as 'zone' option, but only applies to REPLY direction\n"
);
}
......@@ -40,6 +44,8 @@ enum {
O_CTEVENTS,
O_EXPEVENTS,
O_ZONE,
O_ZONE_ORIG,
O_ZONE_REPLY,
};
#define s struct xt_ct_target_info
......@@ -49,8 +55,9 @@ static const struct xt_option_entry ct_opts[] = {
.flags = XTOPT_PUT, XTOPT_POINTER(s, helper)},
{.name = "ctevents", .id = O_CTEVENTS, .type = XTTYPE_STRING},
{.name = "expevents", .id = O_EXPEVENTS, .type = XTTYPE_STRING},
{.name = "zone", .id = O_ZONE, .type = XTTYPE_UINT16,
.flags = XTOPT_PUT, XTOPT_POINTER(s, zone)},
{.name = "zone-orig", .id = O_ZONE_ORIG, .type = XTTYPE_STRING},
{.name = "zone-reply", .id = O_ZONE_REPLY, .type = XTTYPE_STRING},
{.name = "zone", .id = O_ZONE, .type = XTTYPE_STRING},
XTOPT_TABLEEND,
};
#undef s
......@@ -64,8 +71,9 @@ static const struct xt_option_entry ct_opts_v1[] = {
.flags = XTOPT_PUT, XTOPT_POINTER(s, timeout)},
{.name = "ctevents", .id = O_CTEVENTS, .type = XTTYPE_STRING},
{.name = "expevents", .id = O_EXPEVENTS, .type = XTTYPE_STRING},
{.name = "zone", .id = O_ZONE, .type = XTTYPE_UINT16,
.flags = XTOPT_PUT, XTOPT_POINTER(s, zone)},
{.name = "zone-orig", .id = O_ZONE_ORIG, .type = XTTYPE_STRING},
{.name = "zone-reply", .id = O_ZONE_REPLY, .type = XTTYPE_STRING},
{.name = "zone", .id = O_ZONE, .type = XTTYPE_STRING},
XTOPT_TABLEEND,
};
#undef s
......@@ -92,6 +100,45 @@ static const struct event_tbl exp_event_tbl[] = {
{ "new", IPEXP_NEW },
};
static void ct_parse_zone_id(const char *opt, unsigned int opt_id,
uint16_t *zone_id, uint16_t *flags)
{
if (opt_id == O_ZONE_ORIG)
*flags |= XT_CT_ZONE_DIR_ORIG;
if (opt_id == O_ZONE_REPLY)
*flags |= XT_CT_ZONE_DIR_REPL;
*zone_id = 0;
if (strcasecmp(opt, "mark") == 0) {
*flags |= XT_CT_ZONE_MARK;
} else {
uintmax_t val;
if (!xtables_strtoul(opt, NULL, &val, 0, UINT16_MAX))
xtables_error(PARAMETER_PROBLEM,
"Cannot parse %s as a zone ID\n", opt);
*zone_id = (uint16_t)val;
}
}
static void ct_print_zone_id(const char *pfx, uint16_t zone_id, uint16_t flags)
{
printf(" %s", pfx);
if ((flags & (XT_CT_ZONE_DIR_ORIG |
XT_CT_ZONE_DIR_REPL)) == XT_CT_ZONE_DIR_ORIG)
printf("-orig");
if ((flags & (XT_CT_ZONE_DIR_ORIG |
XT_CT_ZONE_DIR_REPL)) == XT_CT_ZONE_DIR_REPL)
printf("-reply");
if (flags & XT_CT_ZONE_MARK)
printf(" mark");
else
printf(" %u", zone_id);
}
static uint32_t ct_parse_events(const struct event_tbl *tbl, unsigned int size,
const char *events)
{
......@@ -138,6 +185,12 @@ static void ct_parse(struct xt_option_call *cb)
case O_NOTRACK:
info->flags |= XT_CT_NOTRACK;
break;
case O_ZONE_ORIG:
case O_ZONE_REPLY:
case O_ZONE:
ct_parse_zone_id(cb->arg, cb->entry->id, &info->zone,
&info->flags);
break;
case O_CTEVENTS:
info->ct_events = ct_parse_events(ct_event_tbl, ARRAY_SIZE(ct_event_tbl), cb->arg);
break;
......@@ -156,6 +209,12 @@ static void ct_parse_v1(struct xt_option_call *cb)
case O_NOTRACK:
info->flags |= XT_CT_NOTRACK;
break;
case O_ZONE_ORIG:
case O_ZONE_REPLY:
case O_ZONE:
ct_parse_zone_id(cb->arg, cb->entry->id, &info->zone,
&info->flags);
break;
case O_CTEVENTS:
info->ct_events = ct_parse_events(ct_event_tbl,
ARRAY_SIZE(ct_event_tbl),
......@@ -185,8 +244,8 @@ static void ct_print(const void *ip, const struct xt_entry_target *target, int n
if (info->exp_events)
ct_print_events("expevents", exp_event_tbl,
ARRAY_SIZE(exp_event_tbl), info->exp_events);
if (info->zone)
printf("zone %u ", info->zone);
if (info->flags & XT_CT_ZONE_MARK || info->zone)
ct_print_zone_id("zone", info->zone, info->flags);
}
static void
......@@ -212,8 +271,8 @@ ct_print_v1(const void *ip, const struct xt_entry_target *target, int numeric)
if (info->exp_events)
ct_print_events("expevents", exp_event_tbl,
ARRAY_SIZE(exp_event_tbl), info->exp_events);
if (info->zone)
printf("zone %u ", info->zone);
if (info->flags & XT_CT_ZONE_MARK || info->zone)
ct_print_zone_id("zone", info->zone, info->flags);
}
static void ct_save(const void *ip, const struct xt_entry_target *target)
......@@ -233,8 +292,8 @@ static void ct_save(const void *ip, const struct xt_entry_target *target)
if (info->exp_events)
ct_print_events("--expevents", exp_event_tbl,
ARRAY_SIZE(exp_event_tbl), info->exp_events);
if (info->zone)
printf(" --zone %u", info->zone);
if (info->flags & XT_CT_ZONE_MARK || info->zone)
ct_print_zone_id("--zone", info->zone, info->flags);
}
static void ct_save_v1(const void *ip, const struct xt_entry_target *target)
......@@ -256,8 +315,8 @@ static void ct_save_v1(const void *ip, const struct xt_entry_target *target)
if (info->exp_events)
ct_print_events("--expevents", exp_event_tbl,
ARRAY_SIZE(exp_event_tbl), info->exp_events);
if (info->zone)
printf(" --zone %u", info->zone);
if (info->flags & XT_CT_ZONE_MARK || info->zone)
ct_print_zone_id("--zone", info->zone, info->flags);
}
static const char *
......
......@@ -20,9 +20,21 @@ the ctmark, not nfmark), \fBnatseqinfo\fP, \fBsecmark\fP (ctsecmark).
Only generate the specified expectation events for this connection.
Possible event types are: \fBnew\fP.
.TP
\fB\-\-zone\fP \fIid\fP
\fB\-\-zone-orig\fP {\fIid\fP|\fBmark\fP}
For traffic coming from ORIGINAL direction, assign this packet to zone
\fIid\fP and only have lookups done in that zone. If \fBmark\fP is used
instead of \fIid\fP, the zone is derived from the packet nfmark.
.TP
\fB\-\-zone-reply\fP {\fIid\fP|\fBmark\fP}
For traffic coming from REPLY direction, assign this packet to zone
\fIid\fP and only have lookups done in that zone. If \fBmark\fP is used
instead of \fIid\fP, the zone is derived from the packet nfmark.
.TP
\fB\-\-zone\fP {\fIid\fP|\fBmark\fP}
Assign this packet to zone \fIid\fP and only have lookups done in that zone.
By default, packets have zone 0.
If \fBmark\fP is used instead of \fIid\fP, the zone is derived from the
packet nfmark. By default, packets have zone 0. This option applies to both
directions.
.TP
\fB\-\-timeout\fP \fIname\fP
Use the timeout policy identified by \fIname\fP for the connection. This is
......
......@@ -158,6 +158,10 @@ set_target_init_v1(struct xt_entry_target *target)
#define SET_TARGET_DEL 0x2
#define SET_TARGET_EXIST 0x4
#define SET_TARGET_TIMEOUT 0x8
#define SET_TARGET_MAP 0x10
#define SET_TARGET_MAP_MARK 0x20
#define SET_TARGET_MAP_PRIO 0x40
#define SET_TARGET_MAP_QUEUE 0x80
static void
parse_target(char **argv, int invert, struct xt_set_info *info,
......@@ -346,6 +350,170 @@ set_target_save_v2(const void *ip, const struct xt_entry_target *target)
print_target("--del-set", &info->del_set);
}
/* Revision 3 */
static void
set_target_help_v3(void)
{
printf("SET target options:\n"
" --add-set name flags [--exist] [--timeout n]\n"
" --del-set name flags\n"
" --map-set name flags"
" [--map-mark] [--map-prio] [--map-queue]\n"
" add/del src/dst IP/port from/to named sets,\n"
" where flags are the comma separated list of\n"
" 'src' and 'dst' specifications.\n");
}
static const struct option set_target_opts_v3[] = {
{.name = "add-set", .has_arg = true, .val = '1'},
{.name = "del-set", .has_arg = true, .val = '2'},
{.name = "exist", .has_arg = false, .val = '3'},
{.name = "timeout", .has_arg = true, .val = '4'},
{.name = "map-set", .has_arg = true, .val = '5'},
{.name = "map-mark", .has_arg = false, .val = '6'},
{.name = "map-prio", .has_arg = false, .val = '7'},
{.name = "map-queue", .has_arg = false, .val = '8'},
XT_GETOPT_TABLEEND,
};
static void
set_target_check_v3(unsigned int flags)
{
if (!(flags & (SET_TARGET_ADD|SET_TARGET_DEL|SET_TARGET_MAP)))
xtables_error(PARAMETER_PROBLEM,
"You must specify either `--add-set' or "
"`--del-set' or `--map-set'");
if (!(flags & SET_TARGET_ADD)) {
if (flags & SET_TARGET_EXIST)
xtables_error(PARAMETER_PROBLEM,
"Flag `--exist' can be used with `--add-set' only");
if (flags & SET_TARGET_TIMEOUT)
xtables_error(PARAMETER_PROBLEM,
"Option `--timeout' can be used with `--add-set' only");
}
if (!(flags & SET_TARGET_MAP)) {
if (flags & SET_TARGET_MAP_MARK)
xtables_error(PARAMETER_PROBLEM,
"Flag `--map-mark' can be used with `--map-set' only");
if (flags & SET_TARGET_MAP_PRIO)
xtables_error(PARAMETER_PROBLEM,
"Flag `--map-prio' can be used with `--map-set' only");
if (flags & SET_TARGET_MAP_QUEUE)
xtables_error(PARAMETER_PROBLEM,
"Flag `--map-queue' can be used with `--map-set' only");
}
if ((flags & SET_TARGET_MAP) && !(flags & (SET_TARGET_MAP_MARK |
SET_TARGET_MAP_PRIO |
SET_TARGET_MAP_QUEUE)))
xtables_error(PARAMETER_PROBLEM,
"You must specify flags `--map-mark' or "
"'--map-prio` or `--map-queue'");
}
static void
set_target_init_v3(struct xt_entry_target *target)
{
struct xt_set_info_target_v3 *info =
(struct xt_set_info_target_v3 *) target->data;
info->add_set.index =
info->del_set.index =
info->map_set.index = IPSET_INVALID_ID;
info->timeout = UINT32_MAX;
}
static int
set_target_parse_v3(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_target **target)
{
struct xt_set_info_target_v3 *myinfo =
(struct xt_set_info_target_v3 *) (*target)->data;
unsigned int timeout;
switch (c) {
case '1': /* --add-set <set> <flags> */
parse_target(argv, invert, &myinfo->add_set, "add-set");
*flags |= SET_TARGET_ADD;
break;
case '2': /* --del-set <set>[:<flags>] <flags> */
parse_target(argv, invert, &myinfo->del_set, "del-set");
*flags |= SET_TARGET_DEL;
break;
case '3':
myinfo->flags |= IPSET_FLAG_EXIST;
*flags |= SET_TARGET_EXIST;
break;
case '4':
if (!xtables_strtoui(optarg, NULL, &timeout, 0, UINT32_MAX - 1))
xtables_error(PARAMETER_PROBLEM,
"Invalid value for option --timeout "
"or out of range 0-%u", UINT32_MAX - 1);
myinfo->timeout = timeout;
*flags |= SET_TARGET_TIMEOUT;
break;
case '5': /* --map-set <set> <flags> */
parse_target(argv, invert, &myinfo->map_set, "map-set");
*flags |= SET_TARGET_MAP;
break;
case '6':
myinfo->flags |= IPSET_FLAG_MAP_SKBMARK;
*flags |= SET_TARGET_MAP_MARK;
break;
case '7':
myinfo->flags |= IPSET_FLAG_MAP_SKBPRIO;
*flags |= SET_TARGET_MAP_PRIO;
break;
case '8':
myinfo->flags |= IPSET_FLAG_MAP_SKBQUEUE;
*flags |= SET_TARGET_MAP_QUEUE;
break;
}
return 1;
}
static void
set_target_print_v3(const void *ip, const struct xt_entry_target *target,
int numeric)
{
const struct xt_set_info_target_v3 *info = (const void *)target->data;
print_target("add-set", &info->add_set);
if (info->flags & IPSET_FLAG_EXIST)
printf(" exist");
if (info->timeout != UINT32_MAX)
printf(" timeout %u", info->timeout);
print_target("del-set", &info->del_set);
print_target("map-set", &info->map_set);
if (info->flags & IPSET_FLAG_MAP_SKBMARK)
printf(" map-mark");
if (info->flags & IPSET_FLAG_MAP_SKBPRIO)
printf(" map-prio");
if (info->flags & IPSET_FLAG_MAP_SKBQUEUE)
printf(" map-queue");
}
static void
set_target_save_v3(const void *ip, const struct xt_entry_target *target)
{
const struct xt_set_info_target_v3 *info = (const void *)target->data;
print_target("--add-set", &info->add_set);
if (info->flags & IPSET_FLAG_EXIST)
printf(" --exist");
if (info->timeout != UINT32_MAX)
printf(" --timeout %u", info->timeout);
print_target("--del-set", &info->del_set);
print_target("--map-set", &info->map_set);
if (info->flags & IPSET_FLAG_MAP_SKBMARK)
printf(" --map-mark");
if (info->flags & IPSET_FLAG_MAP_SKBPRIO)
printf(" --map-prio");
if (info->flags & IPSET_FLAG_MAP_SKBQUEUE)
printf(" --map-queue");
}
static struct xtables_target set_tg_reg[] = {
{
.name = "SET",
......@@ -392,6 +560,21 @@ static struct xtables_target set_tg_reg[] = {
.save = set_target_save_v2,
.extra_opts = set_target_opts_v2,
},
{
.name = "SET",
.revision = 3,
.version = XTABLES_VERSION,
.family = NFPROTO_UNSPEC,
.size = XT_ALIGN(sizeof(struct xt_set_info_target_v3)),
.userspacesize = XT_ALIGN(sizeof(struct xt_set_info_target_v3)),
.help = set_target_help_v3,
.init = set_target_init_v3,
.parse = set_target_parse_v3,
.final_check = set_target_check_v3,
.print = set_target_print_v3,
.save = set_target_save_v3,
.extra_opts = set_target_opts_v3,
},
};
void _init(void)
......
......@@ -6,6 +6,10 @@ add the address(es)/port(s) of the packet to the set
.TP
\fB\-\-del\-set\fP \fIsetname\fP \fIflag\fP[\fB,\fP\fIflag\fP...]
delete the address(es)/port(s) of the packet from the set
.TP
\fB\-\-map\-set\fP \fIsetname\fP \fIflag\fP[\fB,\fP\fIflag\fP...]
[\-\-map\-mark] [\-\-map\-prio] [\-\-map\-queue]
map packet properties (firewall mark, tc priority, hardware queue)
.IP
where \fIflag\fP(s) are
.BR "src"
......@@ -20,6 +24,23 @@ one from the set definition
\fB\-\-exist\fP
when adding an entry if it already exists, reset the timeout value
to the specified one or to the default from the set definition
.TP
\fB\-\-map\-set\fP \fIset\-name\fP
the set-name should be created with --skbinfo option
\fB\-\-map\-mark\fP
map firewall mark to packet by lookup of value in the set
\fB\-\-map\-prio\fP
map traffic control priority to packet by lookup of value in the set
\fB\-\-map\-queue\fP
map hardware NIC queue to packet by lookup of value in the set
.IP
The
\fB\-\-map\-set\fP
option can be used from the mangle table only. The
\fB\-\-map\-prio\fP
and
\fB\-\-map\-queue\fP
flags can be used in the OUTPUT, FORWARD and POSTROUTING chains.
.PP
Use of -j SET requires that ipset kernel support is provided, which, for
standard kernels, is the case since Linux 2.6.39.
......@@ -29,7 +29,12 @@ anymore.
\fB\-\-random\fP
If option
\fB\-\-random\fP
is used then port mapping will be randomized (kernel >= 2.6.21).
is used then port mapping will be randomized through a hash-based algorithm (kernel >= 2.6.21).
.TP
\fB\-\-random-fully\fP
If option
\fB\-\-random-fully\fP
is used then port mapping will be fully randomized through a PRNG (kernel >= 3.14).
.TP
\fB\-\-persistent\fP
Gives a client the same source-/destination-address for each connection.
......
This target will process TCP three-way-handshake parallel in netfilter
context to protect either local or backend system. This target requires
connection tracking because sequence numbers need to be translated.
.TP
\fB\-\-mss\fP \fImaximum segment size\fP
Maximum segment size announced to clients. This must match the backend.
.TP
\fB\-\-wscale\fP \fIwindow scale\fP
Window scale announced to clients. This must match the backend.
.TP
\fB\-\-sack\-perm\fP
Pass client selective acknowledgement option to backend (will be disabled
if not present).
.TP
\fB\-\-timestamps\fP
Pass client timestamp option to backend (will be disabled if not present,
also needed for selective acknowledgement and window scaling).
.PP
Example:
.PP
Determine tcp options used by backend, from an external system
.IP
tcpdump -pni eth0 -c 1 'tcp[tcpflags] == (tcp-syn|tcp-ack)'
.br
port 80 &
.br
telnet 192.0.2.42 80
.br
18:57:24.693307 IP 192.0.2.42.80 > 192.0.2.43.48757:
.br
Flags [S.], seq 360414582, ack 788841994, win 14480,
.br
options [mss 1460,sackOK,
.br
TS val 1409056151 ecr 9690221,
.br
nop,wscale 9],
.br
length 0
.PP
Switch tcp_loose mode off, so conntrack will mark out\-of\-flow
packets as state INVALID.
.IP
echo 0 > /proc/sys/net/netfilter/nf_conntrack_tcp_loose
.PP
Make SYN packets untracked
.IP
iptables \-t raw \-A PREROUTING \-i eth0 \-p tcp \-\-dport 80
\-\-syn \-j CT \-\-notrack
.PP
Catch UNTRACKED (SYN packets) and INVALID (3WHS ACK packets) states
and send them to SYNPROXY. This rule will respond to SYN packets with
SYN+ACK syncookies, create ESTABLISHED for valid client response (3WHS ACK
packets) and drop incorrect cookies. Flags combinations not expected
during 3WHS will not match and continue (e.g. SYN+FIN, SYN+ACK).
.IP
iptables \-A INPUT \-i eth0 \-p tcp \-\-dport 80
\-m state \-\-state UNTRACKED,INVALID \-j SYNPROXY
\-\-sack\-perm \-\-timestamp \-\-mss 1460 \-\-wscale 9
.PP
Drop invalid packets, this will be out\-of\-flow packets that were not
matched by SYNPROXY.
.IP
iptables \-A INPUT \-i eth0 \-p tcp \-\-dport 80 \-m state \-\-state INVALID \-j DROP
......@@ -99,7 +99,7 @@ static struct xtables_target tee_tg_reg[] = {
.revision = 1,
.family = NFPROTO_IPV4,
.size = XT_ALIGN(sizeof(struct xt_tee_tginfo)),
.userspacesize = XT_ALIGN(sizeof(struct xt_tee_tginfo)),
.userspacesize = offsetof(struct xt_tee_tginfo, priv),
.help = tee_tg_help,
.print = tee_tg_print,
.save = tee_tg_save,
......@@ -112,7 +112,7 @@ static struct xtables_target tee_tg_reg[] = {
.revision = 1,
.family = NFPROTO_IPV6,
.size = XT_ALIGN(sizeof(struct xt_tee_tginfo)),
.userspacesize = XT_ALIGN(sizeof(struct xt_tee_tginfo)),
.userspacesize = offsetof(struct xt_tee_tginfo, priv),
.help = tee_tg_help,
.print = tee_tg6_print,
.save = tee_tg6_save,
......
#include <stdio.h>
#include <xtables.h>
#include <linux/netfilter/xt_cgroup.h>
enum {
O_CGROUP = 0,
};
static void cgroup_help(void)
{
printf(
"cgroup match options:\n"
"[!] --cgroup fwid Match cgroup fwid\n");
}
static const struct xt_option_entry cgroup_opts[] = {
{
.name = "cgroup",
.id = O_CGROUP,
.type = XTTYPE_UINT32,
.flags = XTOPT_INVERT | XTOPT_MAND | XTOPT_PUT,
XTOPT_POINTER(struct xt_cgroup_info, id)
},
XTOPT_TABLEEND,
};
static void cgroup_parse(struct xt_option_call *cb)
{
struct xt_cgroup_info *cgroupinfo = cb->data;
xtables_option_parse(cb);
if (cb->invert)
cgroupinfo->invert = true;
}
static void
cgroup_print(const void *ip, const struct xt_entry_match *match, int numeric)
{
const struct xt_cgroup_info *info = (void *) match->data;
printf(" cgroup %s%u", info->invert ? "! ":"", info->id);
}
static void cgroup_save(const void *ip, const struct xt_entry_match *match)
{
const struct xt_cgroup_info *info = (void *) match->data;
printf("%s --cgroup %u", info->invert ? " !" : "", info->id);
}
static struct xtables_match cgroup_match = {
.family = NFPROTO_UNSPEC,
.name = "cgroup",
.version = XTABLES_VERSION,
.size = XT_ALIGN(sizeof(struct xt_cgroup_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_cgroup_info)),
.help = cgroup_help,
.print = cgroup_print,
.save = cgroup_save,
.x6_parse = cgroup_parse,
.x6_options = cgroup_opts,
};
void _init(void)
{
xtables_register_match(&cgroup_match);
}
.TP
[\fB!\fP] \fB\-\-cgroup\fP \fIfwid\fP
Match corresponding cgroup for this packet.
Can be used in the OUTPUT chain to assign particular firewall
policies for aggregated task/jobs on the system. This allows
for more fine-grained firewall policies that only match for a
subset of the system's processes. fwid is the maker set through
the net_cls cgroup's id.
\fBIMPORTANT\fP: when being used in the INPUT chain, the cgroup
matcher is currently only of limited functionality, meaning it
will only match on packets that are processed for local sockets
through early socket demuxing. Therefore, general usage on the
INPUT chain is disadviced unless the implications are well
understood.
.PP
Example:
.IP
iptables \-A OUTPUT \-p tcp \-\-sport 80 \-m cgroup ! \-\-cgroup 1
\-j DROP
.PP
Available since Linux 3.14.
......@@ -29,11 +29,26 @@ static const struct xt_option_entry connlabel_mt_opts[] = {
XTOPT_TABLEEND,
};
/* cannot do this via _init, else static builds might spew error message
* for every iptables invocation.
*/
static void connlabel_open(void)
{
if (map)
return;
map = nfct_labelmap_new(NULL);
if (!map && errno)
xtables_error(RESOURCE_PROBLEM, "cannot open connlabel.conf: %s\n",
strerror(errno));
}
static void connlabel_mt_parse(struct xt_option_call *cb)
{
struct xt_connlabel_mtinfo *info = cb->data;
int tmp;
connlabel_open();
xtables_option_parse(cb);
switch (cb->entry->id) {
......@@ -54,7 +69,11 @@ static void connlabel_mt_parse(struct xt_option_call *cb)
static const char *connlabel_get_name(int b)
{
const char *name = nfct_labelmap_get_name(map, b);
const char *name;
connlabel_open();
name = nfct_labelmap_get_name(map, b);
if (name && strcmp(name, ""))
return name;
return NULL;
......@@ -114,11 +133,5 @@ static struct xtables_match connlabel_mt_reg = {
void _init(void)
{
map = nfct_labelmap_new(NULL);
if (!map) {
fprintf(stderr, "cannot open connlabel.conf, not registering '%s' match: %s\n",
connlabel_mt_reg.name, strerror(errno));
return;
}
xtables_register_match(&connlabel_mt_reg);
}
......@@ -17,7 +17,7 @@
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <stdbool.h>
#include <stdint.h>
......
......@@ -31,12 +31,12 @@ static const struct xt_option_entry devgroup_opts[] = {
XTOPT_TABLEEND,
};
/* array of devgroups from /etc/iproute2/group_map */
/* array of devgroups from /etc/iproute2/group */
static struct xtables_lmap *devgroups;
static void devgroup_init(struct xt_entry_match *match)
{
const char file[] = "/etc/iproute2/group_map";
const char file[] = "/etc/iproute2/group";
devgroups = xtables_lmap_init(file);
if (devgroups == NULL && errno != ENOENT)
fprintf(stderr, "Warning: %s: %s\n", file, strerror(errno));
......@@ -124,7 +124,7 @@ static void devgroup_show(const char *pfx, const struct xt_devgroup_info *info,
if (info->flags & XT_DEVGROUP_INVERT_DST)
printf(" !");
printf(" %sdst-group ", pfx);
print_devgroup(info->src_group, info->src_mask, numeric);
print_devgroup(info->dst_group, info->dst_mask, numeric);
}
}
......
......@@ -21,6 +21,13 @@ static const struct xt_option_entry esp_opts[] = {
XTOPT_TABLEEND,
};
static void esp_init(struct xt_entry_match *m)
{
struct xt_esp *espinfo = (void *)m->data;
espinfo->spis[1] = ~0U;
}
static void esp_parse(struct xt_option_call *cb)
{
struct xt_esp *espinfo = cb->data;
......@@ -86,6 +93,7 @@ static struct xtables_match esp_match = {
.size = XT_ALIGN(sizeof(struct xt_esp)),
.userspacesize = XT_ALIGN(sizeof(struct xt_esp)),
.help = esp_help,
.init = esp_init,
.print = esp_print,
.save = esp_save,
.x6_parse = esp_parse,
......
#include <stdio.h>
#include <xtables.h>
#include <linux/netfilter/xt_ipcomp.h>
enum {
O_compSPI = 0,
O_compRES,
};
static void comp_help(void)
{
printf(
"comp match options:\n"
"[!] --ipcompspi spi[:spi]\n"
" match spi (range)\n");
}
static const struct xt_option_entry comp_opts[] = {
{.name = "ipcompspi", .id = O_compSPI, .type = XTTYPE_UINT32RC,
.flags = XTOPT_INVERT | XTOPT_PUT,
XTOPT_POINTER(struct xt_ipcomp, spis)},
{.name = "compres", .id = O_compRES, .type = XTTYPE_NONE},
XTOPT_TABLEEND,
};
#undef s
static void comp_parse(struct xt_option_call *cb)
{
struct xt_ipcomp *compinfo = cb->data;
xtables_option_parse(cb);
switch (cb->entry->id) {
case O_compSPI:
if (cb->nvals == 1)
compinfo->spis[1] = compinfo->spis[0];
if (cb->invert)
compinfo->invflags |= XT_IPCOMP_INV_SPI;
break;
case O_compRES:
compinfo->hdrres = 1;
break;
}
}
static void
print_spis(const char *name, uint32_t min, uint32_t max,
int invert)
{
const char *inv = invert ? "!" : "";
if (min != 0 || max != 0xFFFFFFFF || invert) {
if (min == max)
printf("%s:%s%u", name, inv, min);
else
printf("%ss:%s%u:%u", name, inv, min, max);
}
}
static void comp_print(const void *ip, const struct xt_entry_match *match,
int numeric)
{
const struct xt_ipcomp *comp = (struct xt_ipcomp *)match->data;
printf(" comp ");
print_spis("spi", comp->spis[0], comp->spis[1],
comp->invflags & XT_IPCOMP_INV_SPI);
if (comp->hdrres)
printf(" reserved");
if (comp->invflags & ~XT_IPCOMP_INV_MASK)
printf(" Unknown invflags: 0x%X",
comp->invflags & ~XT_IPCOMP_INV_MASK);
}
static void comp_save(const void *ip, const struct xt_entry_match *match)
{
const struct xt_ipcomp *compinfo = (struct xt_ipcomp *)match->data;
if (!(compinfo->spis[0] == 0
&& compinfo->spis[1] == 0xFFFFFFFF)) {
printf("%s --ipcompspi ",
(compinfo->invflags & XT_IPCOMP_INV_SPI) ? " !" : "");
if (compinfo->spis[0]
!= compinfo->spis[1])
printf("%u:%u",
compinfo->spis[0],
compinfo->spis[1]);
else
printf("%u",
compinfo->spis[0]);
}
if (compinfo->hdrres != 0 )
printf(" --compres");
}
static struct xtables_match comp_mt_reg = {
.name = "ipcomp",
.version = XTABLES_VERSION,
.family = NFPROTO_UNSPEC,
.size = XT_ALIGN(sizeof(struct xt_ipcomp)),
.userspacesize = XT_ALIGN(sizeof(struct xt_ipcomp)),
.help = comp_help,
.print = comp_print,
.save = comp_save,
.x6_parse = comp_parse,
.x6_options = comp_opts,
};
void
_init(void)
{
xtables_register_match(&comp_mt_reg);
};
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