1 /* Shared library add-on to iptables to add state tracking support. */
8 #include <linux/netfilter/nf_conntrack_common.h>
9 #include <linux/netfilter/xt_state.h>
11 #ifndef XT_STATE_UNTRACKED
12 #define XT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1))
15 /* Function which prints out usage message. */
20 "state match options:\n"
21 " [!] --state [INVALID|ESTABLISHED|NEW|RELATED|UNTRACKED][,...]\n"
22 " State(s) to match\n");
25 static const struct option state_opts[] = {
26 { "state", 1, NULL, '1' },
31 state_parse_state(const char *state, size_t len, struct xt_state_info *sinfo)
33 if (strncasecmp(state, "INVALID", len) == 0)
34 sinfo->statemask |= XT_STATE_INVALID;
35 else if (strncasecmp(state, "NEW", len) == 0)
36 sinfo->statemask |= XT_STATE_BIT(IP_CT_NEW);
37 else if (strncasecmp(state, "ESTABLISHED", len) == 0)
38 sinfo->statemask |= XT_STATE_BIT(IP_CT_ESTABLISHED);
39 else if (strncasecmp(state, "RELATED", len) == 0)
40 sinfo->statemask |= XT_STATE_BIT(IP_CT_RELATED);
41 else if (strncasecmp(state, "UNTRACKED", len) == 0)
42 sinfo->statemask |= XT_STATE_UNTRACKED;
49 state_parse_states(const char *arg, struct xt_state_info *sinfo)
53 while ((comma = strchr(arg, ',')) != NULL) {
54 if (comma == arg || !state_parse_state(arg, comma-arg, sinfo))
55 exit_error(PARAMETER_PROBLEM, "Bad state `%s'", arg);
59 if (strlen(arg) == 0 || !state_parse_state(arg, strlen(arg), sinfo))
60 exit_error(PARAMETER_PROBLEM, "Bad state `%s'", arg);
63 /* Function which parses command options; returns true if it
66 state_parse(int c, char **argv, int invert, unsigned int *flags,
68 struct xt_entry_match **match)
70 struct xt_state_info *sinfo = (struct xt_state_info *)(*match)->data;
74 check_inverse(optarg, &invert, &optind, 0);
76 state_parse_states(argv[optind-1], sinfo);
78 sinfo->statemask = ~sinfo->statemask;
89 /* Final check; must have specified --state. */
90 static void state_final_check(unsigned int flags)
93 exit_error(PARAMETER_PROBLEM, "You must specify `--state'");
96 static void state_print_state(unsigned int statemask)
100 if (statemask & XT_STATE_INVALID) {
101 printf("%sINVALID", sep);
104 if (statemask & XT_STATE_BIT(IP_CT_NEW)) {
105 printf("%sNEW", sep);
108 if (statemask & XT_STATE_BIT(IP_CT_RELATED)) {
109 printf("%sRELATED", sep);
112 if (statemask & XT_STATE_BIT(IP_CT_ESTABLISHED)) {
113 printf("%sESTABLISHED", sep);
116 if (statemask & XT_STATE_UNTRACKED) {
117 printf("%sUNTRACKED", sep);
123 /* Prints out the matchinfo. */
125 state_print(const void *ip,
126 const struct xt_entry_match *match,
129 struct xt_state_info *sinfo = (struct xt_state_info *)match->data;
132 state_print_state(sinfo->statemask);
135 /* Saves the matchinfo in parsable form to stdout. */
136 static void state_save(const void *ip, const struct xt_entry_match *match)
138 struct xt_state_info *sinfo = (struct xt_state_info *)match->data;
141 state_print_state(sinfo->statemask);
144 static struct xtables_match state_match = {
147 .version = XTABLES_VERSION,
148 .size = XT_ALIGN(sizeof(struct xt_state_info)),
149 .userspacesize = XT_ALIGN(sizeof(struct xt_state_info)),
151 .parse = state_parse,
152 .final_check = state_final_check,
153 .print = state_print,
155 .extra_opts = state_opts,
158 static struct xtables_match state_match6 = {
161 .version = XTABLES_VERSION,
162 .size = XT_ALIGN(sizeof(struct xt_state_info)),
163 .userspacesize = XT_ALIGN(sizeof(struct xt_state_info)),
165 .parse = state_parse,
166 .final_check = state_final_check,
167 .print = state_print,
169 .extra_opts = state_opts,
174 xtables_register_match(&state_match);
175 xtables_register_match(&state_match6);