1 /* Ugly hack to make state matching for ipv6 work before iptables-1.4.x is finished */
8 #include <linux/netfilter/nf_conntrack_common.h>
9 #include <linux/netfilter_ipv4/ipt_state.h>
11 #ifndef IPT_STATE_UNTRACKED
12 #define IPT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1))
15 /* Function which prints out usage message. */
20 "state v%s options:\n"
21 " [!] --state [INVALID|ESTABLISHED|NEW|RELATED|UNTRACKED][,...]\n"
22 " State(s) to match\n"
23 "\n", IPTABLES_VERSION
);
26 static struct option opts
[] = {
27 { "state", 1, 0, '1' },
32 parse_state(const char *state
, size_t strlen
, struct ipt_state_info
*sinfo
)
34 if (strncasecmp(state
, "INVALID", strlen
) == 0)
35 sinfo
->statemask
|= IPT_STATE_INVALID
;
36 else if (strncasecmp(state
, "NEW", strlen
) == 0)
37 sinfo
->statemask
|= IPT_STATE_BIT(IP_CT_NEW
);
38 else if (strncasecmp(state
, "ESTABLISHED", strlen
) == 0)
39 sinfo
->statemask
|= IPT_STATE_BIT(IP_CT_ESTABLISHED
);
40 else if (strncasecmp(state
, "RELATED", strlen
) == 0)
41 sinfo
->statemask
|= IPT_STATE_BIT(IP_CT_RELATED
);
42 else if (strncasecmp(state
, "UNTRACKED", strlen
) == 0)
43 sinfo
->statemask
|= IPT_STATE_UNTRACKED
;
50 parse_states(const char *arg
, struct ipt_state_info
*sinfo
)
54 while ((comma
= strchr(arg
, ',')) != NULL
) {
55 if (comma
== arg
|| !parse_state(arg
, comma
-arg
, sinfo
))
56 exit_error(PARAMETER_PROBLEM
, "Bad state `%s'", arg
);
60 if (strlen(arg
) == 0 || !parse_state(arg
, strlen(arg
), sinfo
))
61 exit_error(PARAMETER_PROBLEM
, "Bad state `%s'", arg
);
64 /* Function which parses command options; returns true if it
67 parse(int c
, char **argv
, int invert
, unsigned int *flags
,
68 const struct ip6t_entry
*entry
,
69 unsigned int *nfcache
,
70 struct ip6t_entry_match
**match
)
72 struct ipt_state_info
*sinfo
= (struct ipt_state_info
*)(*match
)->data
;
76 check_inverse(optarg
, &invert
, &optind
, 0);
78 parse_states(argv
[optind
-1], sinfo
);
80 sinfo
->statemask
= ~sinfo
->statemask
;
91 /* Final check; must have specified --state. */
92 static void final_check(unsigned int flags
)
95 exit_error(PARAMETER_PROBLEM
, "You must specify `--state'");
98 static void print_state(unsigned int statemask
)
100 const char *sep
= "";
102 if (statemask
& IPT_STATE_INVALID
) {
103 printf("%sINVALID", sep
);
106 if (statemask
& IPT_STATE_BIT(IP_CT_NEW
)) {
107 printf("%sNEW", sep
);
110 if (statemask
& IPT_STATE_BIT(IP_CT_RELATED
)) {
111 printf("%sRELATED", sep
);
114 if (statemask
& IPT_STATE_BIT(IP_CT_ESTABLISHED
)) {
115 printf("%sESTABLISHED", sep
);
118 if (statemask
& IPT_STATE_UNTRACKED
) {
119 printf("%sUNTRACKED", sep
);
125 /* Prints out the matchinfo. */
127 print(const struct ip6t_ip6
*ip
,
128 const struct ip6t_entry_match
*match
,
131 struct ipt_state_info
*sinfo
= (struct ipt_state_info
*)match
->data
;
134 print_state(sinfo
->statemask
);
137 /* Saves the matchinfo in parsable form to stdout. */
138 static void save(const struct ip6t_ip6
*ip
, const struct ip6t_entry_match
*match
)
140 struct ipt_state_info
*sinfo
= (struct ipt_state_info
*)match
->data
;
143 print_state(sinfo
->statemask
);
146 static struct ip6tables_match state
= {
149 .version
= IPTABLES_VERSION
,
150 .size
= IP6T_ALIGN(sizeof(struct ipt_state_info
)),
151 .userspacesize
= IP6T_ALIGN(sizeof(struct ipt_state_info
)),
154 .final_check
= &final_check
,
162 register_match6(&state
);