Commit dd6b25de authored by Arturo Borrero Gonzalez's avatar Arturo Borrero Gonzalez
Browse files

Merge tag 'upstream/1.6.0+snapshot20161117'

Upstream version 1.6.0+snapshot20161117
parents 8fceaf37 7b095084
:INPUT,FORWARD,OUTPUT
-m dscp --dscp 0;=;OK
-m dscp --dscp 0x3f;=;OK
-m dscp --dscp -1;;FAIL
-m dscp --dscp 0x40;;FAIL
-m dscp --dscp 0x3f --dscp-class CS0;;FAIL
-m dscp --dscp-class CS0;-m dscp --dscp 0x00;OK
-m dscp --dscp-class BE;-m dscp --dscp 0x00;OK
-m dscp --dscp-class EF;-m dscp --dscp 0x2e;OK
-m dscp;;FAIL
......@@ -118,6 +118,36 @@ static void ecn_save(const void *ip, const struct xt_entry_match *match)
}
}
static int ecn_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct xt_ecn_info *einfo =
(const struct xt_ecn_info *)params->match->data;
if (!(einfo->operation & XT_ECN_OP_MATCH_IP))
return 0;
xt_xlate_add(xl, "ip ecn ");
if (einfo->invert)
xt_xlate_add(xl,"!= ");
switch (einfo->ip_ect) {
case 0:
xt_xlate_add(xl, "not-ect");
break;
case 1:
xt_xlate_add(xl, "ect1");
break;
case 2:
xt_xlate_add(xl, "ect0");
break;
case 3:
xt_xlate_add(xl, "ce");
break;
}
return 1;
}
static struct xtables_match ecn_mt_reg = {
.name = "ecn",
.version = XTABLES_VERSION,
......@@ -130,6 +160,7 @@ static struct xtables_match ecn_mt_reg = {
.x6_parse = ecn_parse,
.x6_fcheck = ecn_check,
.x6_options = ecn_opts,
.xlate = ecn_xlate,
};
void _init(void)
......
:INPUT,FORWARD,OUTPUT
-m ecn --ecn-tcp-cwr;;FAIL
-p tcp -m ecn --ecn-tcp-cwr;=;OK
-p tcp -m ecn --ecn-tcp-ece --ecn-tcp-cwr --ecn-ip-ect 2;=;OK
-p tcp -m ecn ! --ecn-tcp-ece ! --ecn-tcp-cwr ! --ecn-ip-ect 2;=;OK
......@@ -86,6 +86,24 @@ static void esp_save(const void *ip, const struct xt_entry_match *match)
}
static int esp_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct xt_esp *espinfo = (struct xt_esp *)params->match->data;
if (!(espinfo->spis[0] == 0 && espinfo->spis[1] == 0xFFFFFFFF)) {
xt_xlate_add(xl, "esp spi%s",
(espinfo->invflags & XT_ESP_INV_SPI) ? " !=" : "");
if (espinfo->spis[0] != espinfo->spis[1])
xt_xlate_add(xl, " %u-%u", espinfo->spis[0],
espinfo->spis[1]);
else
xt_xlate_add(xl, " %u", espinfo->spis[0]);
}
return 1;
}
static struct xtables_match esp_match = {
.family = NFPROTO_UNSPEC,
.name = "esp",
......@@ -98,6 +116,7 @@ static struct xtables_match esp_match = {
.save = esp_save,
.x6_parse = esp_parse,
.x6_options = esp_opts,
.xlate = esp_xlate,
};
void
......
:INPUT,FORWARD,OUTPUT
-p esp -m esp --espspi 0;=;OK
-p esp -m esp --espspi :32;-p esp -m esp --espspi 0:32;OK
-p esp -m esp --espspi 0:4294967295;-p esp -m esp;OK
-p esp -m esp ! --espspi 0:4294967294;=;OK
-p esp -m esp --espspi -1;;FAIL
-p esp -m esp;=;OK
-m esp;;FAIL
......@@ -18,12 +18,14 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <xtables.h>
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/xt_hashlimit.h>
#define XT_HASHLIMIT_BURST 5
#define XT_HASHLIMIT_BURST_MAX 10000
#define XT_HASHLIMIT_BURST_MAX_v1 10000
#define XT_HASHLIMIT_BURST_MAX 1000000
#define XT_HASHLIMIT_BYTE_EXPIRE 15
#define XT_HASHLIMIT_BYTE_EXPIRE_BURST 60
......@@ -98,7 +100,7 @@ static const struct xt_option_entry hashlimit_opts[] = {
{.name = "hashlimit", .id = O_UPTO, .excl = F_ABOVE,
.type = XTTYPE_STRING},
{.name = "hashlimit-burst", .id = O_BURST, .type = XTTYPE_UINT32,
.min = 1, .max = XT_HASHLIMIT_BURST_MAX, .flags = XTOPT_PUT,
.min = 1, .max = XT_HASHLIMIT_BURST_MAX_v1, .flags = XTOPT_PUT,
XTOPT_POINTER(s, cfg.burst)},
{.name = "hashlimit-htable-size", .id = O_HTABLE_SIZE,
.type = XTTYPE_UINT32, .flags = XTOPT_PUT,
......@@ -121,6 +123,36 @@ static const struct xt_option_entry hashlimit_opts[] = {
#undef s
#define s struct xt_hashlimit_mtinfo1
static const struct xt_option_entry hashlimit_mt_opts_v1[] = {
{.name = "hashlimit-upto", .id = O_UPTO, .excl = F_ABOVE,
.type = XTTYPE_STRING, .flags = XTOPT_INVERT},
{.name = "hashlimit-above", .id = O_ABOVE, .excl = F_UPTO,
.type = XTTYPE_STRING, .flags = XTOPT_INVERT},
{.name = "hashlimit", .id = O_UPTO, .excl = F_ABOVE,
.type = XTTYPE_STRING, .flags = XTOPT_INVERT}, /* old name */
{.name = "hashlimit-srcmask", .id = O_SRCMASK, .type = XTTYPE_PLEN},
{.name = "hashlimit-dstmask", .id = O_DSTMASK, .type = XTTYPE_PLEN},
{.name = "hashlimit-burst", .id = O_BURST, .type = XTTYPE_STRING},
{.name = "hashlimit-htable-size", .id = O_HTABLE_SIZE,
.type = XTTYPE_UINT32, .flags = XTOPT_PUT,
XTOPT_POINTER(s, cfg.size)},
{.name = "hashlimit-htable-max", .id = O_HTABLE_MAX,
.type = XTTYPE_UINT32, .flags = XTOPT_PUT,
XTOPT_POINTER(s, cfg.max)},
{.name = "hashlimit-htable-gcinterval", .id = O_HTABLE_GCINT,
.type = XTTYPE_UINT32, .flags = XTOPT_PUT,
XTOPT_POINTER(s, cfg.gc_interval)},
{.name = "hashlimit-htable-expire", .id = O_HTABLE_EXPIRE,
.type = XTTYPE_UINT32, .flags = XTOPT_PUT,
XTOPT_POINTER(s, cfg.expire)},
{.name = "hashlimit-mode", .id = O_MODE, .type = XTTYPE_STRING},
{.name = "hashlimit-name", .id = O_NAME, .type = XTTYPE_STRING,
.flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, name), .min = 1},
XTOPT_TABLEEND,
};
#undef s
#define s struct xt_hashlimit_mtinfo2
static const struct xt_option_entry hashlimit_mt_opts[] = {
{.name = "hashlimit-upto", .id = O_UPTO, .excl = F_ABOVE,
.type = XTTYPE_STRING, .flags = XTOPT_INVERT},
......@@ -150,16 +182,40 @@ static const struct xt_option_entry hashlimit_mt_opts[] = {
};
#undef s
static uint32_t cost_to_bytes(uint32_t cost)
static int
cfg_copy(struct hashlimit_cfg2 *to, const void *from, int revision)
{
if (revision == 1) {
struct hashlimit_cfg1 *cfg = (struct hashlimit_cfg1 *)from;
to->mode = cfg->mode;
to->avg = cfg->avg;
to->burst = cfg->burst;
to->size = cfg->size;
to->max = cfg->max;
to->gc_interval = cfg->gc_interval;
to->expire = cfg->expire;
to->srcmask = cfg->srcmask;
to->dstmask = cfg->dstmask;
} else if (revision == 2) {
memcpy(to, from, sizeof(struct hashlimit_cfg2));
} else {
return -EINVAL;
}
return 0;
}
static uint64_t cost_to_bytes(uint64_t cost)
{
uint32_t r;
uint64_t r;
r = cost ? UINT32_MAX / cost : UINT32_MAX;
r = (r - 1) << XT_HASHLIMIT_BYTE_SHIFT;
return r;
}
static uint64_t bytes_to_cost(uint32_t bytes)
static uint64_t bytes_to_cost(uint64_t bytes)
{
uint32_t r = bytes >> XT_HASHLIMIT_BYTE_SHIFT;
return UINT32_MAX / (r+1);
......@@ -174,63 +230,84 @@ static uint32_t get_factor(int chr)
return 1;
}
static void burst_error_v1(void)
{
xtables_error(PARAMETER_PROBLEM, "bad value for option "
"\"--hashlimit-burst\", or out of range (1-%u).", XT_HASHLIMIT_BURST_MAX_v1);
}
static void burst_error(void)
{
xtables_error(PARAMETER_PROBLEM, "bad value for option "
"\"--hashlimit-burst\", or out of range (1-%u).", XT_HASHLIMIT_BURST_MAX);
}
static uint32_t parse_burst(const char *burst, struct xt_hashlimit_mtinfo1 *info)
static uint64_t parse_burst(const char *burst, int revision)
{
uintmax_t v;
char *end;
if (!xtables_strtoul(burst, &end, &v, 1, UINT32_MAX) ||
(*end == 0 && v > XT_HASHLIMIT_BURST_MAX))
uint64_t max = (revision == 1) ? UINT32_MAX : UINT64_MAX;
uint64_t burst_max = (revision == 1) ?
XT_HASHLIMIT_BURST_MAX_v1 : XT_HASHLIMIT_BURST_MAX;
if (!xtables_strtoul(burst, &end, &v, 1, max) ||
(*end == 0 && v > burst_max)) {
if (revision == 1)
burst_error_v1();
else
burst_error();
}
v *= get_factor(*end);
if (v > UINT32_MAX)
if (v > max)
xtables_error(PARAMETER_PROBLEM, "bad value for option "
"\"--hashlimit-burst\", value \"%s\" too large "
"(max %umb).", burst, UINT32_MAX/1024/1024);
"(max %lumb).", burst, max/1024/1024);
return v;
}
static bool parse_bytes(const char *rate, uint32_t *val, struct hashlimit_mt_udata *ud)
static bool parse_bytes(const char *rate, void *val, struct hashlimit_mt_udata *ud, int revision)
{
unsigned int factor = 1;
uint64_t tmp;
int r;
uint64_t tmp, r;
const char *mode = strstr(rate, "b/s");
uint64_t max = (revision == 1) ? UINT32_MAX : UINT64_MAX;
if (!mode || mode == rate)
return false;
mode--;
r = atoi(rate);
r = atoll(rate);
if (r == 0)
return false;
factor = get_factor(*mode);
tmp = (uint64_t) r * factor;
if (tmp > UINT32_MAX)
if (tmp > max)
xtables_error(PARAMETER_PROBLEM,
"Rate value too large \"%llu\" (max %u)\n",
(unsigned long long)tmp, UINT32_MAX);
"Rate value too large \"%llu\" (max %lu)\n",
(unsigned long long)tmp, max);
*val = bytes_to_cost(tmp);
if (*val == 0)
tmp = bytes_to_cost(tmp);
if (tmp == 0)
xtables_error(PARAMETER_PROBLEM, "Rate too high \"%s\"\n", rate);
ud->mult = XT_HASHLIMIT_BYTE_EXPIRE;
if(revision == 1)
*((uint32_t*)val) = tmp;
else
*((uint64_t*)val) = tmp;
return true;
}
static
int parse_rate(const char *rate, uint32_t *val, struct hashlimit_mt_udata *ud)
int parse_rate(const char *rate, void *val, struct hashlimit_mt_udata *ud, int revision)
{
const char *delim;
uint32_t r;
uint64_t tmp, r;
uint64_t scale = (revision == 1) ? XT_HASHLIMIT_SCALE : XT_HASHLIMIT_SCALE_v2;
ud->mult = 1; /* Seconds by default. */
delim = strchr(rate, '/');
......@@ -249,17 +326,23 @@ int parse_rate(const char *rate, uint32_t *val, struct hashlimit_mt_udata *ud)
else
return 0;
}
r = atoi(rate);
r = atoll(rate);
if (!r)
return 0;
*val = XT_HASHLIMIT_SCALE * ud->mult / r;
if (*val == 0)
tmp = scale * ud->mult / r;
if (tmp == 0)
/*
* The rate maps to infinity. (1/day is the minimum they can
* specify, so we are ok at that end).
*/
xtables_error(PARAMETER_PROBLEM, "Rate too fast \"%s\"\n", rate);
if(revision == 1)
*((uint32_t*)val) = tmp;
else
*((uint64_t*)val) = tmp;
return 1;
}
......@@ -272,7 +355,7 @@ static void hashlimit_init(struct xt_entry_match *m)
}
static void hashlimit_mt4_init(struct xt_entry_match *match)
static void hashlimit_mt4_init_v1(struct xt_entry_match *match)
{
struct xt_hashlimit_mtinfo1 *info = (void *)match->data;
......@@ -283,7 +366,7 @@ static void hashlimit_mt4_init(struct xt_entry_match *match)
info->cfg.dstmask = 32;
}
static void hashlimit_mt6_init(struct xt_entry_match *match)
static void hashlimit_mt6_init_v1(struct xt_entry_match *match)
{
struct xt_hashlimit_mtinfo1 *info = (void *)match->data;
......@@ -294,6 +377,28 @@ static void hashlimit_mt6_init(struct xt_entry_match *match)
info->cfg.dstmask = 128;
}
static void hashlimit_mt4_init(struct xt_entry_match *match)
{
struct xt_hashlimit_mtinfo2 *info = (void *)match->data;
info->cfg.mode = 0;
info->cfg.burst = XT_HASHLIMIT_BURST;
info->cfg.gc_interval = XT_HASHLIMIT_GCINTERVAL;
info->cfg.srcmask = 32;
info->cfg.dstmask = 32;
}
static void hashlimit_mt6_init(struct xt_entry_match *match)
{
struct xt_hashlimit_mtinfo2 *info = (void *)match->data;
info->cfg.mode = 0;
info->cfg.burst = XT_HASHLIMIT_BURST;
info->cfg.gc_interval = XT_HASHLIMIT_GCINTERVAL;
info->cfg.srcmask = 128;
info->cfg.dstmask = 128;
}
/* Parse a 'mode' parameter into the required bitmask */
static int parse_mode(uint32_t *mode, const char *option_arg)
{
......@@ -330,7 +435,7 @@ static void hashlimit_parse(struct xt_option_call *cb)
xtables_option_parse(cb);
switch (cb->entry->id) {
case O_UPTO:
if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata))
if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata, 1))
xtables_param_act(XTF_BAD_VALUE, "hashlimit",
"--hashlimit-upto", cb->arg);
break;
......@@ -342,30 +447,71 @@ static void hashlimit_parse(struct xt_option_call *cb)
}
}
static void hashlimit_mt_parse(struct xt_option_call *cb)
static void hashlimit_mt_parse_v1(struct xt_option_call *cb)
{
struct xt_hashlimit_mtinfo1 *info = cb->data;
xtables_option_parse(cb);
switch (cb->entry->id) {
case O_BURST:
info->cfg.burst = parse_burst(cb->arg, info);
info->cfg.burst = parse_burst(cb->arg, 1);
break;
case O_UPTO:
if (cb->invert)
info->cfg.mode |= XT_HASHLIMIT_INVERT;
if (parse_bytes(cb->arg, &info->cfg.avg, cb->udata, 1))
info->cfg.mode |= XT_HASHLIMIT_BYTES;
else if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata, 1))
xtables_param_act(XTF_BAD_VALUE, "hashlimit",
"--hashlimit-upto", cb->arg);
break;
case O_ABOVE:
if (!cb->invert)
info->cfg.mode |= XT_HASHLIMIT_INVERT;
if (parse_bytes(cb->arg, &info->cfg.avg, cb->udata, 1))
info->cfg.mode |= XT_HASHLIMIT_BYTES;
else if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata, 1))
xtables_param_act(XTF_BAD_VALUE, "hashlimit",
"--hashlimit-above", cb->arg);
break;
case O_MODE:
if (parse_mode(&info->cfg.mode, cb->arg) < 0)
xtables_param_act(XTF_BAD_VALUE, "hashlimit",
"--hashlimit-mode", cb->arg);
break;
case O_SRCMASK:
info->cfg.srcmask = cb->val.hlen;
break;
case O_DSTMASK:
info->cfg.dstmask = cb->val.hlen;
break;
}
}
static void hashlimit_mt_parse(struct xt_option_call *cb)
{
struct xt_hashlimit_mtinfo2 *info = cb->data;
xtables_option_parse(cb);
switch (cb->entry->id) {
case O_BURST:
info->cfg.burst = parse_burst(cb->arg, 2);
break;
case O_UPTO:
if (cb->invert)
info->cfg.mode |= XT_HASHLIMIT_INVERT;
if (parse_bytes(cb->arg, &info->cfg.avg, cb->udata))
if (parse_bytes(cb->arg, &info->cfg.avg, cb->udata, 2))
info->cfg.mode |= XT_HASHLIMIT_BYTES;
else if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata))
else if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata, 2))
xtables_param_act(XTF_BAD_VALUE, "hashlimit",
"--hashlimit-upto", cb->arg);
break;
case O_ABOVE:
if (!cb->invert)
info->cfg.mode |= XT_HASHLIMIT_INVERT;
if (parse_bytes(cb->arg, &info->cfg.avg, cb->udata))
if (parse_bytes(cb->arg, &info->cfg.avg, cb->udata, 2))
info->cfg.mode |= XT_HASHLIMIT_BYTES;
else if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata))
else if (!parse_rate(cb->arg, &info->cfg.avg, cb->udata, 2))
xtables_param_act(XTF_BAD_VALUE, "hashlimit",
"--hashlimit-above", cb->arg);
break;
......@@ -395,7 +541,7 @@ static void hashlimit_check(struct xt_fcheck_call *cb)
info->cfg.expire = udata->mult * 1000; /* from s to msec */
}
static void hashlimit_mt_check(struct xt_fcheck_call *cb)
static void hashlimit_mt_check_v1(struct xt_fcheck_call *cb)
{
const struct hashlimit_mt_udata *udata = cb->udata;
struct xt_hashlimit_mtinfo1 *info = cb->data;
......@@ -411,7 +557,37 @@ static void hashlimit_mt_check(struct xt_fcheck_call *cb)
if (cb->xflags & F_BURST) {
if (info->cfg.burst < cost_to_bytes(info->cfg.avg))
xtables_error(PARAMETER_PROBLEM,
"burst cannot be smaller than %ub", cost_to_bytes(info->cfg.avg));
"burst cannot be smaller than %lub", cost_to_bytes(info->cfg.avg));
burst = info->cfg.burst;
burst /= cost_to_bytes(info->cfg.avg);
if (info->cfg.burst % cost_to_bytes(info->cfg.avg))
burst++;
if (!(cb->xflags & F_HTABLE_EXPIRE))
info->cfg.expire = XT_HASHLIMIT_BYTE_EXPIRE_BURST * 1000;
}
info->cfg.burst = burst;
} else if (info->cfg.burst > XT_HASHLIMIT_BURST_MAX_v1)
burst_error_v1();
}
static void hashlimit_mt_check(struct xt_fcheck_call *cb)
{
const struct hashlimit_mt_udata *udata = cb->udata;
struct xt_hashlimit_mtinfo2 *info = cb->data;
if (!(cb->xflags & (F_UPTO | F_ABOVE)))
xtables_error(PARAMETER_PROBLEM,
"You have to specify --hashlimit");
if (!(cb->xflags & F_HTABLE_EXPIRE))
info->cfg.expire = udata->mult * 1000; /* from s to msec */
if (info->cfg.mode & XT_HASHLIMIT_BYTES) {
uint32_t burst = 0;
if (cb->xflags & F_BURST) {
if (info->cfg.burst < cost_to_bytes(info->cfg.avg))
xtables_error(PARAMETER_PROBLEM,
"burst cannot be smaller than %lub", cost_to_bytes(info->cfg.avg));
burst = info->cfg.burst;
burst /= cost_to_bytes(info->cfg.avg);
......@@ -425,18 +601,25 @@ static void hashlimit_mt_check(struct xt_fcheck_call *cb)
burst_error();
}
static const struct rates
{
struct rates {
const char *name;
uint32_t mult;
} rates[] = { { "day", XT_HASHLIMIT_SCALE*24*60*60 },
uint64_t mult;
} rates_v1[] = { { "day", XT_HASHLIMIT_SCALE*24*60*60 },
{ "hour", XT_HASHLIMIT_SCALE*60*60 },
{ "min", XT_HASHLIMIT_SCALE*60 },
{ "sec", XT_HASHLIMIT_SCALE } };
static uint32_t print_rate(uint32_t period)
static const struct rates rates[] = {
{ "day", XT_HASHLIMIT_SCALE_v2*24*60*60 },
{ "hour", XT_HASHLIMIT_SCALE_v2*60*60 },
{ "min", XT_HASHLIMIT_SCALE_v2*60 },
{ "sec", XT_HASHLIMIT_SCALE_v2 } };
static uint32_t print_rate(uint32_t period, int revision)
{
unsigned int i;
const struct rates *_rates = (revision == 1) ? rates_v1 : rates;
uint64_t scale = (revision == 1) ? XT_HASHLIMIT_SCALE : XT_HASHLIMIT_SCALE_v2;
if (period == 0) {
printf(" %f", INFINITY);
......@@ -444,13 +627,13 @@ static uint32_t print_rate(uint32_t period)
}
for (i = 1; i < ARRAY_SIZE(rates); ++i)
if (period > rates[i].mult
|| rates[i].mult/period < rates[i].mult%period)
if (period > _rates[i].mult
|| _rates[i].mult/period < _rates[i].mult%period)
break;
printf(" %u/%s", rates[i-1].mult / period, rates[i-1].name);
printf(" %lu/%s", _rates[i-1].mult / period, _rates[i-1].name);
/* return in msec */
return rates[i-1].mult / XT_HASHLIMIT_SCALE * 1000;
return _rates[i-1].mult / scale * 1000;
}
static const struct {
......@@ -462,7 +645,7 @@ static const struct {
{ "", 1 },
};
static uint32_t print_bytes(uint32_t avg, uint32_t burst, const char *prefix)
static uint32_t print_bytes(uint64_t avg, uint64_t burst, const char *prefix)
{
unsigned int i;
unsigned long long r;
......@@ -523,7 +706,7 @@ static void hashlimit_print(const void *ip,
uint32_t quantum;
fputs(" limit: avg", stdout);
quantum = print_rate(r->cfg.avg);
quantum = print_rate(r->cfg.avg, 1);
printf(" burst %u", r->cfg.burst);
fputs(" mode", stdout);
print_mode(r->cfg.mode, '-');
......@@ -538,57 +721,89 @@ static void hashlimit_print(const void *ip,
}
static void
hashlimit_mt_print(const struct xt_hashlimit_mtinfo1 *info, unsigned int dmask)
hashlimit_mt_print(const struct hashlimit_cfg2 *cfg, unsigned int dmask, int revision)
{
uint32_t quantum;
if (info->cfg.mode & XT_HASHLIMIT_INVERT)
if (cfg->mode & XT_HASHLIMIT_INVERT)
fputs(" limit: above", stdout);
else
fputs(" limit: up to", stdout);
if (info->cfg.mode & XT_HASHLIMIT_BYTES) {
quantum = print_bytes(info->cfg.avg, info->cfg.burst, "");
if (cfg->mode & XT_HASHLIMIT_BYTES) {
quantum = print_bytes(cfg->avg, cfg->burst, "");
} else {
quantum = print_rate(info->cfg.avg);
printf(" burst %u", info->cfg.burst);
quantum = print_rate(cfg->avg, revision);
printf(" burst %llu", cfg->burst);
}
if (info->cfg.mode & (XT_HASHLIMIT_HASH_SIP | XT_HASHLIMIT_HASH_SPT |
if (cfg->mode & (XT_HASHLIMIT_HASH_SIP | XT_HASHLIMIT_HASH_SPT |
XT_HASHLIMIT_HASH_DIP | XT_HASHLIMIT_HASH_DPT)) {
fputs(" mode", stdout);
print_mode(info->cfg.mode, '-');
print_mode(cfg->mode, '-');
}
if (info->cfg.size != 0)
printf(" htable-size %u", info->cfg.size);
if (info->cfg.max != 0)
printf(" htable-max %u", info->cfg.max);
if (info->cfg.gc_interval != XT_HASHLIMIT_GCINTERVAL)
printf(" htable-gcinterval %u", info->cfg.gc_interval);
if (info->cfg.expire != quantum)
printf(" htable-expire %u", info->cfg.expire);
if (cfg->size != 0)
printf(" htable-size %u", cfg->size);
if (cfg->max != 0)
printf(" htable-max %u", cfg->max);
if (cfg->gc_interval != XT_HASHLIMIT_GCINTERVAL)
printf(" htable-gcinterval %u", cfg->gc_interval);
if (cfg->expire != quantum)
printf(" htable-expire %u", cfg->expire);
if (cfg->srcmask != dmask)
printf(" srcmask %u", cfg->srcmask);
if (cfg->dstmask != dmask)
printf(" dstmask %u", cfg->dstmask);
}
static void
hashlimit_mt4_print_v1(const void *ip, const struct xt_entry_match *match,
int numeric)
{
const struct xt_hashlimit_mtinfo1 *info = (const void *)match->data;
struct hashlimit_cfg2 cfg;
int ret;
ret = cfg_copy(&cfg, (const void *)&info->cfg, 1);
if (ret)
xtables_error(OTHER_PROBLEM, "unknown revision");
if (info->cfg.srcmask != dmask)
printf(" srcmask %u", info->cfg.srcmask);
if (info->cfg.dstmask != dmask)
printf(" dstmask %u", info->cfg.dstmask);
hashlimit_mt_print(&cfg, 32, 1);
}
static void
hashlimit_mt4_print(const void *ip, const struct xt_entry_match *match,
hashlimit_mt6_print_v1(const void *ip, const struct xt_entry_match *match,
int numeric)
{
const struct xt_hashlimit_mtinfo1 *info = (const void *)match->data;
struct hashlimit_cfg2 cfg;
int ret;
ret = cfg_copy(&cfg, (const void *)&info->cfg, 1);
if (ret)
xtables_error(OTHER_PROBLEM, "unknown revision");
hashlimit_mt_print(&cfg, 128, 1);
}
static void
hashlimit_mt4_print(const void *ip, const struct xt_entry_match *match,
int numeric)
{
const struct xt_hashlimit_mtinfo2 *info = (const void *)match->data;
hashlimit_mt_print(info, 32);
hashlimit_mt_print(&info->cfg, 32, 2);
}
static void
hashlimit_mt6_print(const void *ip, const struct xt_entry_match *match,
int numeric)
{
const struct xt_hashlimit_mtinfo1 *info = (const void *)match->data;
const struct xt_hashlimit_mtinfo2 *info = (const void *)match->data;
hashlimit_mt_print(info, 128);
hashlimit_mt_print(&info->cfg, 128, 2);
}
static void hashlimit_save(const void *ip, const struct xt_entry_match *match)
......@@ -597,7 +812,7 @@ static void hashlimit_save(const void *ip, const struct xt_entry_match *match)
uint32_t quantum;
fputs(" --hashlimit", stdout);
quantum = print_rate(r->cfg.avg);
quantum = print_rate(r->cfg.avg, 1);
printf(" --hashlimit-burst %u", r->cfg.burst);
fputs(" --hashlimit-mode", stdout);
......@@ -616,59 +831,89 @@ static void hashlimit_save(const void *ip, const struct xt_entry_match *match)
}
static void
hashlimit_mt_save(const struct xt_hashlimit_mtinfo1 *info, unsigned int dmask)
hashlimit_mt_save(const struct hashlimit_cfg2 *cfg, const char* name, unsigned int dmask, int revision)
{
uint32_t quantum;
if (info->cfg.mode & XT_HASHLIMIT_INVERT)
if (cfg->mode & XT_HASHLIMIT_INVERT)
fputs(" --hashlimit-above", stdout);
else
fputs(" --hashlimit-upto", stdout);
if (info->cfg.mode & XT_HASHLIMIT_BYTES) {
quantum = print_bytes(info->cfg.avg, info->cfg.burst, "--hashlimit-");
if (cfg->mode & XT_HASHLIMIT_BYTES) {
quantum = print_bytes(cfg->avg, cfg->burst, "--hashlimit-");
} else {
quantum = print_rate(info->cfg.avg);
printf(" --hashlimit-burst %u", info->cfg.burst);
quantum = print_rate(cfg->avg, revision);
printf(" --hashlimit-burst %llu", cfg->burst);
}
if (info->cfg.mode & (XT_HASHLIMIT_HASH_SIP | XT_HASHLIMIT_HASH_SPT |
if (cfg->mode & (XT_HASHLIMIT_HASH_SIP | XT_HASHLIMIT_HASH_SPT |
XT_HASHLIMIT_HASH_DIP | XT_HASHLIMIT_HASH_DPT)) {
fputs(" --hashlimit-mode", stdout);
print_mode(info->cfg.mode, ',');
print_mode(cfg->mode, ',');
}
printf(" --hashlimit-name %s", info->name);
printf(" --hashlimit-name %s", name);
if (cfg->size != 0)
printf(" --hashlimit-htable-size %u", cfg->size);
if (cfg->max != 0)
printf(" --hashlimit-htable-max %u", cfg->max);
if (cfg->gc_interval != XT_HASHLIMIT_GCINTERVAL)
printf(" --hashlimit-htable-gcinterval %u", cfg->gc_interval);
if (cfg->expire != quantum)
printf(" --hashlimit-htable-expire %u", cfg->expire);
if (cfg->srcmask != dmask)
printf(" --hashlimit-srcmask %u", cfg->srcmask);
if (cfg->dstmask != dmask)
printf(" --hashlimit-dstmask %u", cfg->dstmask);
}
static void
hashlimit_mt4_save_v1(const void *ip, const struct xt_entry_match *match)
{
const struct xt_hashlimit_mtinfo1 *info = (const void *)match->data;
struct hashlimit_cfg2 cfg;
int ret;
ret = cfg_copy(&cfg, (const void *)&info->cfg, 1);
if (info->cfg.size != 0)
printf(" --hashlimit-htable-size %u", info->cfg.size);
if (info->cfg.max != 0)
printf(" --hashlimit-htable-max %u", info->cfg.max);
if (info->cfg.gc_interval != XT_HASHLIMIT_GCINTERVAL)
printf(" --hashlimit-htable-gcinterval %u", info->cfg.gc_interval);
if (info->cfg.expire != quantum)
printf(" --hashlimit-htable-expire %u", info->cfg.expire);
if (ret)
xtables_error(OTHER_PROBLEM, "unknown revision");
if (info->cfg.srcmask != dmask)
printf(" --hashlimit-srcmask %u", info->cfg.srcmask);
if (info->cfg.dstmask != dmask)
printf(" --hashlimit-dstmask %u", info->cfg.dstmask);
hashlimit_mt_save(&cfg, info->name, 32, 1);
}
static void
hashlimit_mt4_save(const void *ip, const struct xt_entry_match *match)
hashlimit_mt6_save_v1(const void *ip, const struct xt_entry_match *match)
{
const struct xt_hashlimit_mtinfo1 *info = (const void *)match->data;
struct hashlimit_cfg2 cfg;
int ret;
ret = cfg_copy(&cfg, (const void *)&info->cfg, 1);
if (ret)
xtables_error(OTHER_PROBLEM, "unknown revision");
hashlimit_mt_save(&cfg, info->name, 128, 1);
}
static void
hashlimit_mt4_save(const void *ip, const struct xt_entry_match *match)
{
const struct xt_hashlimit_mtinfo2 *info = (const void *)match->data;
hashlimit_mt_save(info, 32);
hashlimit_mt_save(&info->cfg, info->name, 32, 2);
}
static void
hashlimit_mt6_save(const void *ip, const struct xt_entry_match *match)
{
const struct xt_hashlimit_mtinfo1 *info = (const void *)match->data;
const struct xt_hashlimit_mtinfo2 *info = (const void *)match->data;
hashlimit_mt_save(info, 128);
hashlimit_mt_save(&info->cfg, info->name, 128, 2);
}
static struct xtables_match hashlimit_mt_reg[] = {
......@@ -696,6 +941,38 @@ static struct xtables_match hashlimit_mt_reg[] = {
.size = XT_ALIGN(sizeof(struct xt_hashlimit_mtinfo1)),
.userspacesize = offsetof(struct xt_hashlimit_mtinfo1, hinfo),
.help = hashlimit_mt_help,
.init = hashlimit_mt4_init_v1,
.x6_parse = hashlimit_mt_parse_v1,
.x6_fcheck = hashlimit_mt_check_v1,
.print = hashlimit_mt4_print_v1,
.save = hashlimit_mt4_save_v1,
.x6_options = hashlimit_mt_opts_v1,
.udata_size = sizeof(struct hashlimit_mt_udata),
},
{
.version = XTABLES_VERSION,
.name = "hashlimit",
.revision = 1,
.family = NFPROTO_IPV6,
.size = XT_ALIGN(sizeof(struct xt_hashlimit_mtinfo1)),
.userspacesize = offsetof(struct xt_hashlimit_mtinfo1, hinfo),
.help = hashlimit_mt_help,
.init = hashlimit_mt6_init_v1,
.x6_parse = hashlimit_mt_parse_v1,
.x6_fcheck = hashlimit_mt_check_v1,
.print = hashlimit_mt6_print_v1,
.save = hashlimit_mt6_save_v1,
.x6_options = hashlimit_mt_opts_v1,
.udata_size = sizeof(struct hashlimit_mt_udata),
},
{
.version = XTABLES_VERSION,
.name = "hashlimit",
.revision = 2,
.family = NFPROTO_IPV4,
.size = XT_ALIGN(sizeof(struct xt_hashlimit_mtinfo2)),
.userspacesize = offsetof(struct xt_hashlimit_mtinfo2, hinfo),
.help = hashlimit_mt_help,
.init = hashlimit_mt4_init,
.x6_parse = hashlimit_mt_parse,
.x6_fcheck = hashlimit_mt_check,
......@@ -707,10 +984,10 @@ static struct xtables_match hashlimit_mt_reg[] = {
{
.version = XTABLES_VERSION,
.name = "hashlimit",
.revision = 1,
.revision = 2,
.family = NFPROTO_IPV6,
.size = XT_ALIGN(sizeof(struct xt_hashlimit_mtinfo1)),
.userspacesize = offsetof(struct xt_hashlimit_mtinfo1, hinfo),
.size = XT_ALIGN(sizeof(struct xt_hashlimit_mtinfo2)),
.userspacesize = offsetof(struct xt_hashlimit_mtinfo2, hinfo),
.help = hashlimit_mt_help,
.init = hashlimit_mt6_init,
.x6_parse = hashlimit_mt_parse,
......
:INPUT,FORWARD,OUTPUT
-m hashlimit --hashlimit-above 1/sec --hashlimit-burst 5 --hashlimit-name mini1;=;OK
-m hashlimit --hashlimit-above 1000000/sec --hashlimit-burst 5 --hashlimit-name mini1;=;OK
-m hashlimit --hashlimit-above 1/min --hashlimit-burst 5 --hashlimit-name mini1;=;OK
-m hashlimit --hashlimit-above 1/hour --hashlimit-burst 5 --hashlimit-name mini1;=;OK
# kernel says "xt_hashlimit: overflow, try lower: 864000000/5"
-m hashlimit --hashlimit-above 1/day --hashlimit-burst 5 --hashlimit-name mini1;;FAIL
-m hashlimit --hashlimit-upto 1/sec --hashlimit-burst 5 --hashlimit-name mini1;=;OK
-m hashlimit --hashlimit-upto 1000000/sec --hashlimit-burst 5 --hashlimit-name mini1;=;OK
-m hashlimit --hashlimit-upto 1/min --hashlimit-burst 5 --hashlimit-name mini1;=;OK
-m hashlimit --hashlimit-upto 1/hour --hashlimit-burst 5 --hashlimit-name mini1;=;OK
# kernel says "xt_hashlimit: overflow, try lower: 864000000/5"
-m hashlimit --hashlimit-upto 1/day --hashlimit-burst 5 --hashlimit-name mini1;;FAIL
-m hashlimit --hashlimit-upto 1/sec --hashlimit-burst 1 --hashlimit-name mini1 --hashlimit-htable-expire 2000;=;OK
-m hashlimit --hashlimit-upto 1/sec --hashlimit-burst 1 --hashlimit-mode srcip --hashlimit-name mini1 --hashlimit-htable-expire 2000;=;OK
-m hashlimit --hashlimit-upto 1/sec --hashlimit-burst 1 --hashlimit-mode dstip --hashlimit-name mini1 --hashlimit-htable-expire 2000;=;OK
-m hashlimit --hashlimit-upto 1/sec --hashlimit-burst 1 --hashlimit-mode dstip --hashlimit-name mini1 --hashlimit-htable-max 2000 --hashlimit-htable-expire 2000;=;OK
-m hashlimit --hashlimit-upto 1/sec --hashlimit-burst 1 --hashlimit-mode dstip --hashlimit-name mini1 --hashlimit-htable-max 2000 --hashlimit-htable-gcinterval 60000 --hashlimit-htable-expire 2000;=;OK
-m hashlimit --hashlimit-upto 1/sec --hashlimit-name mini1;-m hashlimit --hashlimit-upto 1/sec --hashlimit-burst 5 --hashlimit-name mini1;OK
-m hashlimit --hashlimit-upto 4kb/s --hashlimit-burst 400kb --hashlimit-name mini5;=;OK
-m hashlimit --hashlimit-upto 10mb/s --hashlimit-name mini6;=;OK
-m hashlimit --hashlimit-upto 123456b/s --hashlimit-burst 1mb --hashlimit-name mini7;=;OK
# should work, it says "iptables v1.4.15: burst cannot be smaller than 96b"
# ERROR: cannot load: iptables -A INPUT -m hashlimit --hashlimit-upto 96b/s --hashlimit-burst 5 --hashlimit-name mini1
# -m hashlimit --hashlimit-upto 96b/s --hashlimit-burst 5 --hashlimit-name mini1;=;OK
-m hashlimit --hashlimit-name mini1;;FAIL
-m hashlimit --hashlimit-upto 1/sec;;FAIL
-m hashlimit;;FAIL
......@@ -45,6 +45,21 @@ static void helper_save(const void *ip, const struct xt_entry_match *match)
xtables_save_string(info->name);
}
static int helper_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct xt_helper_info *info = (const void *)params->match->data;
if (params->escape_quotes)
xt_xlate_add(xl, "ct helper%s \\\"%s\\\"",
info->invert ? " !=" : "", info->name);
else
xt_xlate_add(xl, "ct helper%s \"%s\"",
info->invert ? " !=" : "", info->name);
return 1;
}
static struct xtables_match helper_match = {
.family = NFPROTO_UNSPEC,
.name = "helper",
......@@ -55,6 +70,7 @@ static struct xtables_match helper_match = {
.save = helper_save,
.x6_parse = helper_parse,
.x6_options = helper_opts,
.xlate = helper_xlate,
};
void _init(void)
......
:INPUT,FORWARD,OUTPUT
-m helper --helper ftp;=;OK
# should be OK?
# ERROR: should fail: iptables -A INPUT -m helper --helper wrong
# -m helper --helper wrong;;FAIL
-m helper;;FAIL
......@@ -95,6 +95,23 @@ static void comp_save(const void *ip, const struct xt_entry_match *match)
printf(" --compres");
}
static int comp_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct xt_ipcomp *compinfo =
(struct xt_ipcomp *)params->match->data;
xt_xlate_add(xl, "comp cpi %s",
compinfo->invflags & XT_IPCOMP_INV_SPI ? "!= " : "");
if (compinfo->spis[0] != compinfo->spis[1])
xt_xlate_add(xl, "%u-%u", compinfo->spis[0],
compinfo->spis[1]);
else
xt_xlate_add(xl, "%u", compinfo->spis[0]);
return 1;
}
static struct xtables_match comp_mt_reg = {
.name = "ipcomp",
.version = XTABLES_VERSION,
......@@ -106,6 +123,7 @@ static struct xtables_match comp_mt_reg = {
.save = comp_save,
.x6_parse = comp_parse,
.x6_options = comp_opts,
.xlate = comp_xlate,
};
void
......
......@@ -104,7 +104,8 @@ static void iprange_parse(struct xt_option_call *cb)
info->flags |= IPRANGE_SRC;
if (cb->invert)
info->flags |= IPRANGE_SRC_INV;
iprange_parse_range(cb->arg, range, NFPROTO_IPV4, "--src-range");
iprange_parse_range(cb->arg, range,
NFPROTO_IPV4, "--src-range");
info->src.min_ip = range[0].ip;
info->src.max_ip = range[1].ip;
break;
......@@ -112,7 +113,8 @@ static void iprange_parse(struct xt_option_call *cb)
info->flags |= IPRANGE_DST;
if (cb->invert)
info->flags |= IPRANGE_DST_INV;
iprange_parse_range(cb->arg, range, NFPROTO_IPV4, "--dst-range");
iprange_parse_range(cb->arg, range,
NFPROTO_IPV4, "--dst-range");
info->dst.min_ip = range[0].ip;
info->dst.max_ip = range[1].ip;
break;
......@@ -267,13 +269,15 @@ static void iprange_mt4_save(const void *ip, const struct xt_entry_match *match)
if (info->flags & IPRANGE_SRC) {
if (info->flags & IPRANGE_SRC_INV)
printf(" !");
printf(" --src-range %s", xtables_ipaddr_to_numeric(&info->src_min.in));
printf(" --src-range %s",
xtables_ipaddr_to_numeric(&info->src_min.in));
printf("-%s", xtables_ipaddr_to_numeric(&info->src_max.in));
}
if (info->flags & IPRANGE_DST) {
if (info->flags & IPRANGE_DST_INV)
printf(" !");
printf(" --dst-range %s", xtables_ipaddr_to_numeric(&info->dst_min.in));
printf(" --dst-range %s",
xtables_ipaddr_to_numeric(&info->dst_min.in));
printf("-%s", xtables_ipaddr_to_numeric(&info->dst_max.in));
}
}
......@@ -285,17 +289,105 @@ static void iprange_mt6_save(const void *ip, const struct xt_entry_match *match)
if (info->flags & IPRANGE_SRC) {
if (info->flags & IPRANGE_SRC_INV)
printf(" !");
printf(" --src-range %s", xtables_ip6addr_to_numeric(&info->src_min.in6));
printf(" --src-range %s",
xtables_ip6addr_to_numeric(&info->src_min.in6));
printf("-%s", xtables_ip6addr_to_numeric(&info->src_max.in6));
}
if (info->flags & IPRANGE_DST) {
if (info->flags & IPRANGE_DST_INV)
printf(" !");
printf(" --dst-range %s", xtables_ip6addr_to_numeric(&info->dst_min.in6));
printf(" --dst-range %s",
xtables_ip6addr_to_numeric(&info->dst_min.in6));
printf("-%s", xtables_ip6addr_to_numeric(&info->dst_max.in6));
}
}
static void
print_iprange_xlate(const struct ipt_iprange *range,
struct xt_xlate *xl)
{
const unsigned char *byte_min, *byte_max;
byte_min = (const unsigned char *)&range->min_ip;
byte_max = (const unsigned char *)&range->max_ip;
xt_xlate_add(xl, " %u.%u.%u.%u-%u.%u.%u.%u ",
byte_min[0], byte_min[1], byte_min[2], byte_min[3],
byte_max[0], byte_max[1], byte_max[2], byte_max[3]);
}
static int iprange_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct ipt_iprange_info *info = (const void *)params->match->data;
char *space = "";
if (info->flags & IPRANGE_SRC) {
xt_xlate_add(xl, "ip saddr%s",
info->flags & IPRANGE_SRC_INV ? " !=" : "");
print_iprange_xlate(&info->src, xl);
space = " ";
}
if (info->flags & IPRANGE_DST) {
xt_xlate_add(xl, "%sip daddr%s", space,
info->flags & IPRANGE_DST_INV ? " !=" : "");
print_iprange_xlate(&info->dst, xl);
}
return 1;
}
static int iprange_mt4_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct xt_iprange_mtinfo *info =
(const void *)params->match->data;
char *space = "";
if (info->flags & IPRANGE_SRC) {
xt_xlate_add(xl, "ip saddr%s %s",
info->flags & IPRANGE_SRC_INV ? " !=" : "",
xtables_ipaddr_to_numeric(&info->src_min.in));
xt_xlate_add(xl, "-%s",
xtables_ipaddr_to_numeric(&info->src_max.in));
space = " ";
}
if (info->flags & IPRANGE_DST) {
xt_xlate_add(xl, "%sip daddr%s %s", space,
info->flags & IPRANGE_DST_INV ? " !=" : "",
xtables_ipaddr_to_numeric(&info->dst_min.in));
xt_xlate_add(xl, "-%s",
xtables_ipaddr_to_numeric(&info->dst_max.in));
}
return 1;
}
static int iprange_mt6_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct xt_iprange_mtinfo *info =
(const void *)params->match->data;
char *space = "";
if (info->flags & IPRANGE_SRC) {
xt_xlate_add(xl, "ip6 saddr%s %s",
info->flags & IPRANGE_SRC_INV ? " !=" : "",
xtables_ip6addr_to_numeric(&info->src_min.in6));
xt_xlate_add(xl, "-%s",
xtables_ip6addr_to_numeric(&info->src_max.in6));
space = " ";
}
if (info->flags & IPRANGE_DST) {
xt_xlate_add(xl, "%sip6 daddr%s %s", space,
info->flags & IPRANGE_DST_INV ? " !=" : "",
xtables_ip6addr_to_numeric(&info->dst_min.in6));
xt_xlate_add(xl, "-%s",
xtables_ip6addr_to_numeric(&info->dst_max.in6));
}
return 1;
}
static struct xtables_match iprange_mt_reg[] = {
{
.version = XTABLES_VERSION,
......@@ -310,6 +402,7 @@ static struct xtables_match iprange_mt_reg[] = {
.print = iprange_print,
.save = iprange_save,
.x6_options = iprange_mt_opts,
.xlate = iprange_xlate,
},
{
.version = XTABLES_VERSION,
......@@ -324,6 +417,7 @@ static struct xtables_match iprange_mt_reg[] = {
.print = iprange_mt4_print,
.save = iprange_mt4_save,
.x6_options = iprange_mt_opts,
.xlate = iprange_mt4_xlate,
},
{
.version = XTABLES_VERSION,
......@@ -338,6 +432,7 @@ static struct xtables_match iprange_mt_reg[] = {
.print = iprange_mt6_print,
.save = iprange_mt6_save,
.x6_options = iprange_mt_opts,
.xlate = iprange_mt6_xlate,
},
};
......
:INPUT,FORWARD,OUTPUT
-m iprange --src-range 1.1.1.1-1.1.1.10;=;OK
-m iprange ! --src-range 1.1.1.1-1.1.1.10;=;OK
-m iprange --dst-range 1.1.1.1-1.1.1.10;=;OK
-m iprange ! --dst-range 1.1.1.1-1.1.1.10;=;OK
# it shows -A INPUT -m iprange --src-range 1.1.1.1-1.1.1.1, should we support this?
# ERROR: should fail: iptables -A INPUT -m iprange --src-range 1.1.1.1
# -m iprange --src-range 1.1.1.1;;FAIL
# ERROR: should fail: iptables -A INPUT -m iprange --dst-range 1.1.1.1
#-m iprange --dst-range 1.1.1.1;;FAIL
-m iprange;;FAIL
......@@ -56,6 +56,21 @@ static void length_save(const void *ip, const struct xt_entry_match *match)
printf("%u:%u", info->min, info->max);
}
static int length_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct xt_length_info *info = (void *)params->match->data;
xt_xlate_add(xl, "meta length %s", info->invert ? "!= " : "");
if (info->min == info->max)
xt_xlate_add(xl, "%u", info->min);
else
xt_xlate_add(xl, "%u-%u", info->min, info->max);
return 1;
}
static struct xtables_match length_match = {
.family = NFPROTO_UNSPEC,
.name = "length",
......@@ -67,6 +82,7 @@ static struct xtables_match length_match = {
.save = length_save,
.x6_parse = length_parse,
.x6_options = length_opts,
.xlate = length_xlate,
};
void _init(void)
......
:INPUT,FORWARD,OUTPUT
-m length --length 1;=;OK
-m length --length :2;-m length --length 0:2;OK
-m length --length 0:3;=;OK
-m length --length 4:;=;OK
-m length --length 0:65535;=;OK
-m length ! --length 0:65535;=;OK
-m length --length 0:65536;;FAIL
-m length --length -1:65535;;FAIL
-m length;;FAIL
......@@ -152,6 +152,44 @@ static void limit_save(const void *ip, const struct xt_entry_match *match)
printf(" --limit-burst %u", r->burst);
}
static const struct rates rates_xlate[] = {
{ "day", XT_LIMIT_SCALE * 24 * 60 * 60 },
{ "hour", XT_LIMIT_SCALE * 60 * 60 },
{ "minute", XT_LIMIT_SCALE * 60 },
{ "second", XT_LIMIT_SCALE }
};
static void print_rate_xlate(uint32_t period, struct xt_xlate *xl)
{
unsigned int i;
if (period == 0) {
xt_xlate_add(xl, " %f", INFINITY);
return;
}
for (i = 1; i < ARRAY_SIZE(rates); ++i)
if (period > rates_xlate[i].mult ||
rates_xlate[i].mult / period < rates_xlate[i].mult % period)
break;
xt_xlate_add(xl, " %u/%s", rates_xlate[i - 1].mult / period,
rates_xlate[i - 1].name);
}
static int limit_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct xt_rateinfo *r = (const void *)params->match->data;
xt_xlate_add(xl, "limit rate");
print_rate_xlate(r->avg, xl);
if (r->burst != 0)
xt_xlate_add(xl, " burst %u packets", r->burst);
return 1;
}
static struct xtables_match limit_match = {
.family = NFPROTO_UNSPEC,
.name = "limit",
......@@ -164,6 +202,7 @@ static struct xtables_match limit_match = {
.print = limit_print,
.save = limit_save,
.x6_options = limit_opts,
.xlate = limit_xlate,
};
void _init(void)
......
:INPUT,FORWARD,OUTPUT
-m limit --limit 1/sec;=;OK
-m limit --limit 1/min;=;OK
-m limit --limit 1000/hour;=;OK
-m limit --limit 1000/day;=;OK
-m limit --limit 1/sec --limit-burst 1;=;OK
......@@ -50,6 +50,7 @@ static void
mac_print(const void *ip, const struct xt_entry_match *match, int numeric)
{
const struct xt_mac_info *info = (void *)match->data;
printf(" MAC");
if (info->invert)
......@@ -69,6 +70,27 @@ static void mac_save(const void *ip, const struct xt_entry_match *match)
print_mac(info->srcaddr);
}
static void print_mac_xlate(const unsigned char *macaddress,
struct xt_xlate *xl)
{
unsigned int i;
xt_xlate_add(xl, "%02x", macaddress[0]);
for (i = 1; i < ETH_ALEN; ++i)
xt_xlate_add(xl, ":%02x", macaddress[i]);
}
static int mac_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct xt_mac_info *info = (void *)params->match->data;
xt_xlate_add(xl, "ether saddr%s ", info->invert ? " !=" : "");
print_mac_xlate(info->srcaddr, xl);
return 1;
}
static struct xtables_match mac_match = {
.family = NFPROTO_UNSPEC,
.name = "mac",
......@@ -80,6 +102,7 @@ static struct xtables_match mac_match = {
.print = mac_print,
.save = mac_save,
.x6_options = mac_opts,
.xlate = mac_xlate,
};
void _init(void)
......
:INPUT,FORWARD
-m mac --mac-source 42:01:02:03:04:05;=;OK
-m mac --mac-source 42:01:02:03:04;=;FAIL
-m mac --mac-source 42:01:02:03:04:05:06;=;FAIL
-m mac;;FAIL
......@@ -74,22 +74,30 @@ static void inaddrcpy(struct in_addr *dst, struct in_addr *src)
static struct in_addr *host_to_addr(const char *name, unsigned int *naddr)
{
struct hostent *host;
struct in_addr *addr;
struct addrinfo hints;
struct addrinfo *res, *p;
int err;
unsigned int i;
*naddr = 0;
if ((host = gethostbyname(name)) != NULL) {
if (host->h_addrtype != AF_INET ||
host->h_length != sizeof(struct in_addr))
return (struct in_addr *) NULL;
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_CANONNAME;
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_RAW;
while (host->h_addr_list[*naddr] != (char *) NULL)
*naddr = 0;
err = getaddrinfo(name, NULL, &hints, &res);
if (err != 0)
return NULL;
else {
for (p = res; p != NULL; p = p->ai_next)
(*naddr)++;
addr = xtables_calloc(*naddr, sizeof(struct in_addr));
for (i = 0; i < *naddr; i++)
inaddrcpy(&(addr[i]),
(struct in_addr *) host->h_addr_list[i]);
for (i = 0, p = res; p != NULL; p = p->ai_next)
memcpy(&addr[i++],
&((const struct sockaddr_in *)p->ai_addr)->sin_addr,
sizeof(struct in_addr));
freeaddrinfo(res);
return addr;
}
......
......@@ -102,6 +102,48 @@ mark_save(const void *ip, const struct xt_entry_match *match)
print_mark(info->mark, info->mask);
}
static void
print_mark_xlate(struct xt_xlate *xl, unsigned int mark,
unsigned int mask, uint32_t op)
{
if (mask != 0xffffffffU)
xt_xlate_add(xl, " and 0x%x %s 0x%x", mask,
op == XT_OP_EQ ? "==" : "!=", mark);
else
xt_xlate_add(xl, " %s0x%x",
op == XT_OP_EQ ? "" : "!= ", mark);
}
static int mark_mt_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct xt_mark_mtinfo1 *info = (const void *)params->match->data;
enum xt_op op = XT_OP_EQ;
if (info->invert)
op = XT_OP_NEQ;
xt_xlate_add(xl, "mark");
print_mark_xlate(xl, info->mark, info->mask, op);
return 1;
}
static int mark_xlate(struct xt_xlate *xl,
const struct xt_xlate_mt_params *params)
{
const struct xt_mark_info *info = (const void *)params->match->data;
enum xt_op op = XT_OP_EQ;
if (info->invert)
op = XT_OP_NEQ;
xt_xlate_add(xl, "mark");
print_mark_xlate(xl, info->mark, info->mask, op);
return 1;
}
static struct xtables_match mark_mt_reg[] = {
{
.family = NFPROTO_UNSPEC,
......@@ -115,6 +157,7 @@ static struct xtables_match mark_mt_reg[] = {
.save = mark_save,
.x6_parse = mark_parse,
.x6_options = mark_mt_opts,
.xlate = mark_xlate,
},
{
.version = XTABLES_VERSION,
......@@ -128,6 +171,7 @@ static struct xtables_match mark_mt_reg[] = {
.save = mark_mt_save,
.x6_parse = mark_mt_parse,
.x6_options = mark_mt_opts,
.xlate = mark_mt_xlate,
},
};
......
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