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 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
|
/* Shared library add-on to iptables to add state tracking support. */
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#include <xtables.h>
#include <linux/netfilter/nf_conntrack_common.h>
#include <linux/netfilter/xt_state.h>
#ifndef XT_STATE_UNTRACKED
#define XT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1))
#endif
static void
state_help(void)
{
printf(
"state match options:\n"
" [!] --state [INVALID|ESTABLISHED|NEW|RELATED|UNTRACKED][,...]\n"
" State(s) to match\n");
}
static const struct option state_opts[] = {
{ "state", 1, NULL, '1' },
{ .name = NULL }
};
static int
state_parse_state(const char *state, size_t len, struct xt_state_info *sinfo)
{
if (strncasecmp(state, "INVALID", len) == 0)
sinfo->statemask |= XT_STATE_INVALID;
else if (strncasecmp(state, "NEW", len) == 0)
sinfo->statemask |= XT_STATE_BIT(IP_CT_NEW);
else if (strncasecmp(state, "ESTABLISHED", len) == 0)
sinfo->statemask |= XT_STATE_BIT(IP_CT_ESTABLISHED);
else if (strncasecmp(state, "RELATED", len) == 0)
sinfo->statemask |= XT_STATE_BIT(IP_CT_RELATED);
else if (strncasecmp(state, "UNTRACKED", len) == 0)
sinfo->statemask |= XT_STATE_UNTRACKED;
else
return 0;
return 1;
}
static void
state_parse_states(const char *arg, struct xt_state_info *sinfo)
{
const char *comma;
while ((comma = strchr(arg, ',')) != NULL) {
if (comma == arg || !state_parse_state(arg, comma-arg, sinfo))
xtables_error(PARAMETER_PROBLEM, "Bad state \"%s\"", arg);
arg = comma+1;
}
if (!*arg)
xtables_error(PARAMETER_PROBLEM, "\"--state\" requires a list of "
"states with no spaces, e.g. "
"ESTABLISHED,RELATED");
if (strlen(arg) == 0 || !state_parse_state(arg, strlen(arg), sinfo))
xtables_error(PARAMETER_PROBLEM, "Bad state \"%s\"", arg);
}
static int
state_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry,
struct xt_entry_match **match)
{
struct xt_state_info *sinfo = (struct xt_state_info *)(*match)->data;
switch (c) {
case '1':
xtables_check_inverse(optarg, &invert, &optind, 0, argv);
state_parse_states(optarg, sinfo);
if (invert)
sinfo->statemask = ~sinfo->statemask;
*flags = 1;
break;
default:
return 0;
}
return 1;
}
static void state_final_check(unsigned int flags)
{
if (!flags)
xtables_error(PARAMETER_PROBLEM, "You must specify \"--state\"");
}
static void state_print_state(unsigned int statemask)
{
const char *sep = "";
if (statemask & XT_STATE_INVALID) {
printf("%sINVALID", sep);
sep = ",";
}
if (statemask & XT_STATE_BIT(IP_CT_NEW)) {
printf("%sNEW", sep);
sep = ",";
}
if (statemask & XT_STATE_BIT(IP_CT_RELATED)) {
printf("%sRELATED", sep);
sep = ",";
}
if (statemask & XT_STATE_BIT(IP_CT_ESTABLISHED)) {
printf("%sESTABLISHED", sep);
sep = ",";
}
if (statemask & XT_STATE_UNTRACKED) {
printf("%sUNTRACKED", sep);
sep = ",";
}
printf(" ");
}
static void
state_print(const void *ip,
const struct xt_entry_match *match,
int numeric)
{
const struct xt_state_info *sinfo = (const void *)match->data;
printf("state ");
state_print_state(sinfo->statemask);
}
static void state_save(const void *ip, const struct xt_entry_match *match)
{
const struct xt_state_info *sinfo = (const void *)match->data;
printf("--state ");
state_print_state(sinfo->statemask);
}
static struct xtables_match state_match = {
.family = NFPROTO_UNSPEC,
.name = "state",
.version = XTABLES_VERSION,
.size = XT_ALIGN(sizeof(struct xt_state_info)),
.userspacesize = XT_ALIGN(sizeof(struct xt_state_info)),
.help = state_help,
.parse = state_parse,
.final_check = state_final_check,
.print = state_print,
.save = state_save,
.extra_opts = state_opts,
};
void _init(void)
{
xtables_register_match(&state_match);
}
|