1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
#include <stdio.h>
#include <xtables.h>
#include <linux/netfilter/xt_esp.h>
enum {
O_ESPSPI = 0,
};
static void esp_help(void)
{
printf(
"esp match options:\n"
"[!] --espspi spi[:spi]\n"
" match spi (range)\n");
}
static const struct xt_option_entry esp_opts[] = {
{.name = "espspi", .id = O_ESPSPI, .type = XTTYPE_UINT32RC,
.flags = XTOPT_INVERT | XTOPT_PUT,
XTOPT_POINTER(struct xt_esp, spis)},
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;
xtables_option_parse(cb);
if (cb->nvals == 1)
espinfo->spis[1] = espinfo->spis[0];
if (cb->invert)
espinfo->invflags |= XT_ESP_INV_SPI;
}
static bool skip_spis_match(uint32_t min, uint32_t max, bool inv)
{
return min == 0 && max == UINT32_MAX && !inv;
}
static void
print_spis(const char *name, uint32_t min, uint32_t max,
int invert)
{
const char *inv = invert ? "!" : "";
if (!skip_spis_match(min, max, invert)) {
if (min == max)
printf(" %s:%s%u", name, inv, min);
else
printf(" %ss:%s%u:%u", name, inv, min, max);
}
}
static void
esp_print(const void *ip, const struct xt_entry_match *match, int numeric)
{
const struct xt_esp *esp = (struct xt_esp *)match->data;
printf(" esp");
print_spis("spi", esp->spis[0], esp->spis[1],
esp->invflags & XT_ESP_INV_SPI);
if (esp->invflags & ~XT_ESP_INV_MASK)
printf(" Unknown invflags: 0x%X",
esp->invflags & ~XT_ESP_INV_MASK);
}
static void esp_save(const void *ip, const struct xt_entry_match *match)
{
const struct xt_esp *espinfo = (struct xt_esp *)match->data;
bool inv_spi = espinfo->invflags & XT_ESP_INV_SPI;
if (!skip_spis_match(espinfo->spis[0], espinfo->spis[1], inv_spi)) {
printf("%s --espspi ", inv_spi ? " !" : "");
if (espinfo->spis[0]
!= espinfo->spis[1])
printf("%u:%u",
espinfo->spis[0],
espinfo->spis[1]);
else
printf("%u",
espinfo->spis[0]);
}
}
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;
bool inv_spi = espinfo->invflags & XT_ESP_INV_SPI;
if (!skip_spis_match(espinfo->spis[0], espinfo->spis[1], inv_spi)) {
xt_xlate_add(xl, "esp spi%s", 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]);
} else if (afinfo->family == NFPROTO_IPV4) {
xt_xlate_add(xl, "meta l4proto esp");
} else if (afinfo->family == NFPROTO_IPV6) {
xt_xlate_add(xl, "exthdr esp exists");
} else {
return 0;
}
return 1;
}
static struct xtables_match esp_match = {
.family = NFPROTO_UNSPEC,
.name = "esp",
.version = XTABLES_VERSION,
.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,
.x6_options = esp_opts,
.xlate = esp_xlate,
};
void
_init(void)
{
xtables_register_match(&esp_match);
}
|