blob: 7b93bfafce185b00d3496f98360afacd18410a34 [file] [log] [blame]
Patrick McHardy9fdbaa72010-03-08 13:57:24 +01001#include <stdio.h>
2#include <string.h>
Patrick McHardy9fdbaa72010-03-08 13:57:24 +01003#include <xtables.h>
4#include <linux/netfilter/nf_conntrack_common.h>
5#include <linux/netfilter/xt_CT.h>
6
7static 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"
Jan Engelhardt89b6c322010-03-11 00:49:48 +010013" --ctevents event[,event...] Generate specified conntrack events for connection\n"
Patrick McHardy9fdbaa72010-03-08 13:57:24 +010014" --expevents event[,event...] Generate specified expectation events for connection\n"
15" --zone ID Assign/Lookup connection in zone ID\n"
16 );
17}
18
Jan Engelhardta05562e2011-03-06 17:47:03 +010019enum {
20 O_NOTRACK = 0,
21 O_HELPER,
22 O_CTEVENTS,
23 O_EXPEVENTS,
24 O_ZONE,
Patrick McHardy9fdbaa72010-03-08 13:57:24 +010025};
26
Jan Engelhardta05562e2011-03-06 17:47:03 +010027#define s struct xt_ct_target_info
28static 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,
Patrick McHardy9fdbaa72010-03-08 13:57:24 +010037};
Jan Engelhardta05562e2011-03-06 17:47:03 +010038#undef s
Patrick McHardy9fdbaa72010-03-08 13:57:24 +010039
40struct event_tbl {
41 const char *name;
42 unsigned int event;
43};
44
45static 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
58static const struct event_tbl exp_event_tbl[] = {
59 { "new", IPEXP_NEW },
60};
61
62static 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++) {
Pablo Neira Ayusobed2ba92010-05-09 21:47:33 +020071 if (strcmp(t, tbl[i].name))
Patrick McHardy9fdbaa72010-03-08 13:57:24 +010072 continue;
Pablo Neira Ayusobed2ba92010-05-09 21:47:33 +020073 mask |= 1 << tbl[i].event;
Patrick McHardy9fdbaa72010-03-08 13:57:24 +010074 break;
75 }
76
77 if (i == size)
78 xtables_error(PARAMETER_PROBLEM, "Unknown event type \"%s\"", t);
79 }
80
81 return mask;
82}
83
84static 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
Jan Engelhardt73866352010-12-18 02:04:59 +010090 printf(" %s ", pfx);
Patrick McHardy9fdbaa72010-03-08 13:57:24 +010091 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 }
Patrick McHardy9fdbaa72010-03-08 13:57:24 +010097}
98
Jan Engelhardta05562e2011-03-06 17:47:03 +010099static void ct_parse(struct xt_option_call *cb)
Patrick McHardy9fdbaa72010-03-08 13:57:24 +0100100{
Jan Engelhardta05562e2011-03-06 17:47:03 +0100101 struct xt_ct_target_info *info = cb->data;
Patrick McHardy9fdbaa72010-03-08 13:57:24 +0100102
Jan Engelhardta05562e2011-03-06 17:47:03 +0100103 xtables_option_parse(cb);
104 switch (cb->entry->id) {
105 case O_NOTRACK:
Patrick McHardy9fdbaa72010-03-08 13:57:24 +0100106 info->flags |= XT_CT_NOTRACK;
107 break;
Jan Engelhardta05562e2011-03-06 17:47:03 +0100108 case O_CTEVENTS:
109 info->ct_events = ct_parse_events(ct_event_tbl, ARRAY_SIZE(ct_event_tbl), cb->arg);
Patrick McHardy9fdbaa72010-03-08 13:57:24 +0100110 break;
Jan Engelhardta05562e2011-03-06 17:47:03 +0100111 case O_EXPEVENTS:
112 info->exp_events = ct_parse_events(exp_event_tbl, ARRAY_SIZE(exp_event_tbl), cb->arg);
Patrick McHardy9fdbaa72010-03-08 13:57:24 +0100113 break;
Patrick McHardy9fdbaa72010-03-08 13:57:24 +0100114 }
Patrick McHardy9fdbaa72010-03-08 13:57:24 +0100115}
116
117static 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
Jan Engelhardt73866352010-12-18 02:04:59 +0100122 printf(" CT");
Patrick McHardy9fdbaa72010-03-08 13:57:24 +0100123 if (info->flags & XT_CT_NOTRACK)
Jan Engelhardt73866352010-12-18 02:04:59 +0100124 printf(" notrack");
Patrick McHardy9fdbaa72010-03-08 13:57:24 +0100125 if (info->helper[0])
Jan Engelhardt73866352010-12-18 02:04:59 +0100126 printf(" helper %s", info->helper);
Patrick McHardy9fdbaa72010-03-08 13:57:24 +0100127 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);
Patrick McHardy9f27e6b2010-04-20 14:26:47 +0200133 if (info->zone)
134 printf("zone %u ", info->zone);
Patrick McHardy9fdbaa72010-03-08 13:57:24 +0100135}
136
137static 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)
Jan Engelhardt73866352010-12-18 02:04:59 +0100143 printf(" --notrack");
Patrick McHardy9fdbaa72010-03-08 13:57:24 +0100144 if (info->helper[0])
Jan Engelhardt73866352010-12-18 02:04:59 +0100145 printf(" --helper %s", info->helper);
Patrick McHardy9fdbaa72010-03-08 13:57:24 +0100146 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);
Patrick McHardy9f27e6b2010-04-20 14:26:47 +0200152 if (info->zone)
Jan Engelhardt73866352010-12-18 02:04:59 +0100153 printf(" --zone %u", info->zone);
Patrick McHardy9fdbaa72010-03-08 13:57:24 +0100154}
155
156static 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,
Patrick McHardy9fdbaa72010-03-08 13:57:24 +0100163 .print = ct_print,
164 .save = ct_save,
Jan Engelhardta05562e2011-03-06 17:47:03 +0100165 .x6_parse = ct_parse,
166 .x6_options = ct_opts,
Patrick McHardy9fdbaa72010-03-08 13:57:24 +0100167};
168
169void _init(void)
170{
171 xtables_register_target(&ct_target);
172}