• 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_CT.h>
6 
ct_help(void)7 static void ct_help(void)
8 {
9 	printf(
10 "CT target options:\n"
11 " --notrack			Don't track connection\n"
12 " --helper name			Use conntrack helper 'name' for connection\n"
13 " --ctevents event[,event...]	Generate specified conntrack events for connection\n"
14 " --expevents event[,event...]	Generate specified expectation events for connection\n"
15 " --zone ID			Assign/Lookup connection in zone ID\n"
16 	);
17 }
18 
19 enum {
20 	O_NOTRACK = 0,
21 	O_HELPER,
22 	O_CTEVENTS,
23 	O_EXPEVENTS,
24 	O_ZONE,
25 };
26 
27 #define s struct xt_ct_target_info
28 static const struct xt_option_entry ct_opts[] = {
29 	{.name = "notrack", .id = O_NOTRACK, .type = XTTYPE_NONE},
30 	{.name = "helper", .id = O_HELPER, .type = XTTYPE_STRING,
31 	 .flags = XTOPT_PUT, XTOPT_POINTER(s, helper)},
32 	{.name = "ctevents", .id = O_CTEVENTS, .type = XTTYPE_STRING},
33 	{.name = "expevents", .id = O_EXPEVENTS, .type = XTTYPE_STRING},
34 	{.name = "zone", .id = O_ZONE, .type = XTTYPE_UINT16,
35 	 .flags = XTOPT_PUT, XTOPT_POINTER(s, zone)},
36 	XTOPT_TABLEEND,
37 };
38 #undef s
39 
40 struct event_tbl {
41 	const char	*name;
42 	unsigned int	event;
43 };
44 
45 static const struct event_tbl ct_event_tbl[] = {
46 	{ "new",		IPCT_NEW },
47 	{ "related",		IPCT_RELATED },
48 	{ "destroy",		IPCT_DESTROY },
49 	{ "reply",		IPCT_REPLY },
50 	{ "assured",		IPCT_ASSURED },
51 	{ "protoinfo",		IPCT_PROTOINFO },
52 	{ "helper",		IPCT_HELPER },
53 	{ "mark",		IPCT_MARK },
54 	{ "natseqinfo",		IPCT_NATSEQADJ },
55 	{ "secmark",		IPCT_SECMARK },
56 };
57 
58 static const struct event_tbl exp_event_tbl[] = {
59 	{ "new",		IPEXP_NEW },
60 };
61 
ct_parse_events(const struct event_tbl * tbl,unsigned int size,const char * events)62 static uint32_t ct_parse_events(const struct event_tbl *tbl, unsigned int size,
63 				const char *events)
64 {
65 	char str[strlen(events) + 1], *e = str, *t;
66 	unsigned int mask = 0, i;
67 
68 	strcpy(str, events);
69 	while ((t = strsep(&e, ","))) {
70 		for (i = 0; i < size; i++) {
71 			if (strcmp(t, tbl[i].name))
72 				continue;
73 			mask |= 1 << tbl[i].event;
74 			break;
75 		}
76 
77 		if (i == size)
78 			xtables_error(PARAMETER_PROBLEM, "Unknown event type \"%s\"", t);
79 	}
80 
81 	return mask;
82 }
83 
ct_print_events(const char * pfx,const struct event_tbl * tbl,unsigned int size,uint32_t mask)84 static void ct_print_events(const char *pfx, const struct event_tbl *tbl,
85 			    unsigned int size, uint32_t mask)
86 {
87 	const char *sep = "";
88 	unsigned int i;
89 
90 	printf(" %s ", pfx);
91 	for (i = 0; i < size; i++) {
92 		if (mask & (1 << tbl[i].event)) {
93 			printf("%s%s", sep, tbl[i].name);
94 			sep = ",";
95 		}
96 	}
97 }
98 
ct_parse(struct xt_option_call * cb)99 static void ct_parse(struct xt_option_call *cb)
100 {
101 	struct xt_ct_target_info *info = cb->data;
102 
103 	xtables_option_parse(cb);
104 	switch (cb->entry->id) {
105 	case O_NOTRACK:
106 		info->flags |= XT_CT_NOTRACK;
107 		break;
108 	case O_CTEVENTS:
109 		info->ct_events = ct_parse_events(ct_event_tbl, ARRAY_SIZE(ct_event_tbl), cb->arg);
110 		break;
111 	case O_EXPEVENTS:
112 		info->exp_events = ct_parse_events(exp_event_tbl, ARRAY_SIZE(exp_event_tbl), cb->arg);
113 		break;
114 	}
115 }
116 
ct_print(const void * ip,const struct xt_entry_target * target,int numeric)117 static void ct_print(const void *ip, const struct xt_entry_target *target, int numeric)
118 {
119 	const struct xt_ct_target_info *info =
120 		(const struct xt_ct_target_info *)target->data;
121 
122 	printf(" CT");
123 	if (info->flags & XT_CT_NOTRACK)
124 		printf(" notrack");
125 	if (info->helper[0])
126 		printf(" helper %s", info->helper);
127 	if (info->ct_events)
128 		ct_print_events("ctevents", ct_event_tbl,
129 				ARRAY_SIZE(ct_event_tbl), info->ct_events);
130 	if (info->exp_events)
131 		ct_print_events("expevents", exp_event_tbl,
132 				ARRAY_SIZE(exp_event_tbl), info->exp_events);
133 	if (info->zone)
134 		printf("zone %u ", info->zone);
135 }
136 
ct_save(const void * ip,const struct xt_entry_target * target)137 static void ct_save(const void *ip, const struct xt_entry_target *target)
138 {
139 	const struct xt_ct_target_info *info =
140 		(const struct xt_ct_target_info *)target->data;
141 
142 	if (info->flags & XT_CT_NOTRACK)
143 		printf(" --notrack");
144 	if (info->helper[0])
145 		printf(" --helper %s", info->helper);
146 	if (info->ct_events)
147 		ct_print_events("--ctevents", ct_event_tbl,
148 				ARRAY_SIZE(ct_event_tbl), info->ct_events);
149 	if (info->exp_events)
150 		ct_print_events("--expevents", exp_event_tbl,
151 				ARRAY_SIZE(exp_event_tbl), info->exp_events);
152 	if (info->zone)
153 		printf(" --zone %u", info->zone);
154 }
155 
156 static struct xtables_target ct_target = {
157 	.family		= NFPROTO_UNSPEC,
158 	.name		= "CT",
159 	.version	= XTABLES_VERSION,
160 	.size		= XT_ALIGN(sizeof(struct xt_ct_target_info)),
161 	.userspacesize	= offsetof(struct xt_ct_target_info, ct),
162 	.help		= ct_help,
163 	.print		= ct_print,
164 	.save		= ct_save,
165 	.x6_parse	= ct_parse,
166 	.x6_options	= ct_opts,
167 };
168 
_init(void)169 void _init(void)
170 {
171 	xtables_register_target(&ct_target);
172 }
173