You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
175 lines
4.3 KiB
175 lines
4.3 KiB
#include <stdio.h> |
|
#include <string.h> |
|
#include <xtables.h> |
|
#include <linux/netfilter/xt_connbytes.h> |
|
|
|
enum { |
|
O_CONNBYTES = 0, |
|
O_CONNBYTES_DIR, |
|
O_CONNBYTES_MODE, |
|
}; |
|
|
|
static void connbytes_help(void) |
|
{ |
|
printf( |
|
"connbytes match options:\n" |
|
" [!] --connbytes from:[to]\n" |
|
" --connbytes-dir [original, reply, both]\n" |
|
" --connbytes-mode [packets, bytes, avgpkt]\n"); |
|
} |
|
|
|
static const struct xt_option_entry connbytes_opts[] = { |
|
{.name = "connbytes", .id = O_CONNBYTES, .type = XTTYPE_UINT64RC, |
|
.flags = XTOPT_MAND | XTOPT_INVERT}, |
|
{.name = "connbytes-dir", .id = O_CONNBYTES_DIR, .type = XTTYPE_STRING, |
|
.flags = XTOPT_MAND}, |
|
{.name = "connbytes-mode", .id = O_CONNBYTES_MODE, |
|
.type = XTTYPE_STRING, .flags = XTOPT_MAND}, |
|
XTOPT_TABLEEND, |
|
}; |
|
|
|
static void connbytes_parse(struct xt_option_call *cb) |
|
{ |
|
struct xt_connbytes_info *sinfo = cb->data; |
|
unsigned long long i; |
|
|
|
xtables_option_parse(cb); |
|
switch (cb->entry->id) { |
|
case O_CONNBYTES: |
|
sinfo->count.from = cb->val.u64_range[0]; |
|
sinfo->count.to = UINT64_MAX; |
|
if (cb->nvals == 2) |
|
sinfo->count.to = cb->val.u64_range[1]; |
|
|
|
if (sinfo->count.to < sinfo->count.from) |
|
xtables_error(PARAMETER_PROBLEM, "%llu should be less than %llu", |
|
(unsigned long long)sinfo->count.from, |
|
(unsigned long long)sinfo->count.to); |
|
if (cb->invert) { |
|
i = sinfo->count.from; |
|
sinfo->count.from = sinfo->count.to; |
|
sinfo->count.to = i; |
|
} |
|
break; |
|
case O_CONNBYTES_DIR: |
|
if (strcmp(cb->arg, "original") == 0) |
|
sinfo->direction = XT_CONNBYTES_DIR_ORIGINAL; |
|
else if (strcmp(cb->arg, "reply") == 0) |
|
sinfo->direction = XT_CONNBYTES_DIR_REPLY; |
|
else if (strcmp(cb->arg, "both") == 0) |
|
sinfo->direction = XT_CONNBYTES_DIR_BOTH; |
|
else |
|
xtables_error(PARAMETER_PROBLEM, |
|
"Unknown --connbytes-dir `%s'", cb->arg); |
|
break; |
|
case O_CONNBYTES_MODE: |
|
if (strcmp(cb->arg, "packets") == 0) |
|
sinfo->what = XT_CONNBYTES_PKTS; |
|
else if (strcmp(cb->arg, "bytes") == 0) |
|
sinfo->what = XT_CONNBYTES_BYTES; |
|
else if (strcmp(cb->arg, "avgpkt") == 0) |
|
sinfo->what = XT_CONNBYTES_AVGPKT; |
|
else |
|
xtables_error(PARAMETER_PROBLEM, |
|
"Unknown --connbytes-mode `%s'", cb->arg); |
|
break; |
|
} |
|
} |
|
|
|
static void print_mode(const struct xt_connbytes_info *sinfo) |
|
{ |
|
switch (sinfo->what) { |
|
case XT_CONNBYTES_PKTS: |
|
fputs(" packets", stdout); |
|
break; |
|
case XT_CONNBYTES_BYTES: |
|
fputs(" bytes", stdout); |
|
break; |
|
case XT_CONNBYTES_AVGPKT: |
|
fputs(" avgpkt", stdout); |
|
break; |
|
default: |
|
fputs(" unknown", stdout); |
|
break; |
|
} |
|
} |
|
|
|
static void print_direction(const struct xt_connbytes_info *sinfo) |
|
{ |
|
switch (sinfo->direction) { |
|
case XT_CONNBYTES_DIR_ORIGINAL: |
|
fputs(" original", stdout); |
|
break; |
|
case XT_CONNBYTES_DIR_REPLY: |
|
fputs(" reply", stdout); |
|
break; |
|
case XT_CONNBYTES_DIR_BOTH: |
|
fputs(" both", stdout); |
|
break; |
|
default: |
|
fputs(" unknown", stdout); |
|
break; |
|
} |
|
} |
|
|
|
static void print_from_to(const struct xt_connbytes_info *sinfo, const char *prefix) |
|
{ |
|
unsigned long long from, to; |
|
|
|
if (sinfo->count.from > sinfo->count.to) { |
|
fputs(" !", stdout); |
|
from = sinfo->count.to; |
|
to = sinfo->count.from; |
|
} else { |
|
to = sinfo->count.to; |
|
from = sinfo->count.from; |
|
} |
|
printf(" %sconnbytes %llu", prefix, from); |
|
if (to && to < UINT64_MAX) |
|
printf(":%llu", to); |
|
} |
|
|
|
static void |
|
connbytes_print(const void *ip, const struct xt_entry_match *match, int numeric) |
|
{ |
|
const struct xt_connbytes_info *sinfo = (const void *)match->data; |
|
|
|
print_from_to(sinfo, ""); |
|
|
|
fputs(" connbytes mode", stdout); |
|
print_mode(sinfo); |
|
|
|
fputs(" connbytes direction", stdout); |
|
print_direction(sinfo); |
|
} |
|
|
|
static void connbytes_save(const void *ip, const struct xt_entry_match *match) |
|
{ |
|
const struct xt_connbytes_info *sinfo = (const void *)match->data; |
|
|
|
print_from_to(sinfo, "--"); |
|
|
|
fputs(" --connbytes-mode", stdout); |
|
print_mode(sinfo); |
|
|
|
fputs(" --connbytes-dir", stdout); |
|
print_direction(sinfo); |
|
} |
|
|
|
static struct xtables_match connbytes_match = { |
|
.family = NFPROTO_UNSPEC, |
|
.name = "connbytes", |
|
.version = XTABLES_VERSION, |
|
.size = XT_ALIGN(sizeof(struct xt_connbytes_info)), |
|
.userspacesize = XT_ALIGN(sizeof(struct xt_connbytes_info)), |
|
.help = connbytes_help, |
|
.print = connbytes_print, |
|
.save = connbytes_save, |
|
.x6_parse = connbytes_parse, |
|
.x6_options = connbytes_opts, |
|
}; |
|
|
|
void _init(void) |
|
{ |
|
xtables_register_match(&connbytes_match); |
|
}
|
|
|