• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdio.h>
2 #include <string.h>
3 #include <xtables.h>
4 #include <linux/netfilter/nf_conntrack_common.h>
5 #include <linux/netfilter/xt_state.h>
6 
7 #ifndef XT_STATE_UNTRACKED
8 #define XT_STATE_UNTRACKED (1 << (IP_CT_NUMBER + 1))
9 #endif
10 
11 enum {
12 	O_STATE = 0,
13 };
14 
15 static void
state_help(void)16 state_help(void)
17 {
18 	printf(
19 "state match options:\n"
20 " [!] --state [INVALID|ESTABLISHED|NEW|RELATED|UNTRACKED][,...]\n"
21 "				State(s) to match\n");
22 }
23 
24 static const struct xt_option_entry state_opts[] = {
25 	{.name = "state", .id = O_STATE, .type = XTTYPE_STRING,
26 	 .flags = XTOPT_MAND},
27 	XTOPT_TABLEEND,
28 };
29 
30 static int
state_parse_state(const char * state,size_t len,struct xt_state_info * sinfo)31 state_parse_state(const char *state, size_t len, struct xt_state_info *sinfo)
32 {
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;
43 	else
44 		return 0;
45 	return 1;
46 }
47 
48 static void
state_parse_states(const char * arg,struct xt_state_info * sinfo)49 state_parse_states(const char *arg, struct xt_state_info *sinfo)
50 {
51 	const char *comma;
52 
53 	while ((comma = strchr(arg, ',')) != NULL) {
54 		if (comma == arg || !state_parse_state(arg, comma-arg, sinfo))
55 			xtables_error(PARAMETER_PROBLEM, "Bad state \"%s\"", arg);
56 		arg = comma+1;
57 	}
58 	if (!*arg)
59 		xtables_error(PARAMETER_PROBLEM, "\"--state\" requires a list of "
60 					      "states with no spaces, e.g. "
61 					      "ESTABLISHED,RELATED");
62 	if (strlen(arg) == 0 || !state_parse_state(arg, strlen(arg), sinfo))
63 		xtables_error(PARAMETER_PROBLEM, "Bad state \"%s\"", arg);
64 }
65 
state_parse(struct xt_option_call * cb)66 static void state_parse(struct xt_option_call *cb)
67 {
68 	struct xt_state_info *sinfo = cb->data;
69 
70 	xtables_option_parse(cb);
71 	state_parse_states(cb->arg, sinfo);
72 	if (cb->invert)
73 		sinfo->statemask = ~sinfo->statemask;
74 }
75 
state_print_state(unsigned int statemask)76 static void state_print_state(unsigned int statemask)
77 {
78 	const char *sep = "";
79 
80 	if (statemask & XT_STATE_INVALID) {
81 		printf("%sINVALID", sep);
82 		sep = ",";
83 	}
84 	if (statemask & XT_STATE_BIT(IP_CT_NEW)) {
85 		printf("%sNEW", sep);
86 		sep = ",";
87 	}
88 	if (statemask & XT_STATE_BIT(IP_CT_RELATED)) {
89 		printf("%sRELATED", sep);
90 		sep = ",";
91 	}
92 	if (statemask & XT_STATE_BIT(IP_CT_ESTABLISHED)) {
93 		printf("%sESTABLISHED", sep);
94 		sep = ",";
95 	}
96 	if (statemask & XT_STATE_UNTRACKED) {
97 		printf("%sUNTRACKED", sep);
98 		sep = ",";
99 	}
100 }
101 
102 static void
state_print(const void * ip,const struct xt_entry_match * match,int numeric)103 state_print(const void *ip,
104       const struct xt_entry_match *match,
105       int numeric)
106 {
107 	const struct xt_state_info *sinfo = (const void *)match->data;
108 
109 	printf(" state ");
110 	state_print_state(sinfo->statemask);
111 }
112 
state_save(const void * ip,const struct xt_entry_match * match)113 static void state_save(const void *ip, const struct xt_entry_match *match)
114 {
115 	const struct xt_state_info *sinfo = (const void *)match->data;
116 
117 	printf(" --state ");
118 	state_print_state(sinfo->statemask);
119 }
120 
121 static struct xtables_match state_match = {
122 	.family		= NFPROTO_UNSPEC,
123 	.name		= "state",
124 	.version	= XTABLES_VERSION,
125 	.size		= XT_ALIGN(sizeof(struct xt_state_info)),
126 	.userspacesize	= XT_ALIGN(sizeof(struct xt_state_info)),
127 	.help		= state_help,
128 	.print		= state_print,
129 	.save		= state_save,
130 	.x6_parse	= state_parse,
131 	.x6_options	= state_opts,
132 };
133 
_init(void)134 void _init(void)
135 {
136 	xtables_register_match(&state_match);
137 }
138