libxt_CT.c revision 50f19190a60ff7d69e88406a71a2f27e09008566
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 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" 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 19static void ct_help_v1(void) 20{ 21 printf( 22"CT target options:\n" 23" --notrack Don't track connection\n" 24" --helper name Use conntrack helper 'name' for connection\n" 25" --timeout name Use timeout policy 'name' for connection\n" 26" --ctevents event[,event...] Generate specified conntrack events for connection\n" 27" --expevents event[,event...] Generate specified expectation events for connection\n" 28" --zone ID Assign/Lookup connection in zone ID\n" 29 ); 30} 31 32enum { 33 O_NOTRACK = 0, 34 O_HELPER, 35 O_TIMEOUT, 36 O_CTEVENTS, 37 O_EXPEVENTS, 38 O_ZONE, 39}; 40 41#define s struct xt_ct_target_info 42static const struct xt_option_entry ct_opts[] = { 43 {.name = "notrack", .id = O_NOTRACK, .type = XTTYPE_NONE}, 44 {.name = "helper", .id = O_HELPER, .type = XTTYPE_STRING, 45 .flags = XTOPT_PUT, XTOPT_POINTER(s, helper)}, 46 {.name = "ctevents", .id = O_CTEVENTS, .type = XTTYPE_STRING}, 47 {.name = "expevents", .id = O_EXPEVENTS, .type = XTTYPE_STRING}, 48 {.name = "zone", .id = O_ZONE, .type = XTTYPE_UINT16, 49 .flags = XTOPT_PUT, XTOPT_POINTER(s, zone)}, 50 XTOPT_TABLEEND, 51}; 52#undef s 53 54#define s struct xt_ct_target_info_v1 55static const struct xt_option_entry ct_opts_v1[] = { 56 {.name = "notrack", .id = O_NOTRACK, .type = XTTYPE_NONE}, 57 {.name = "helper", .id = O_HELPER, .type = XTTYPE_STRING, 58 .flags = XTOPT_PUT, XTOPT_POINTER(s, helper)}, 59 {.name = "timeout", .id = O_TIMEOUT, .type = XTTYPE_STRING, 60 .flags = XTOPT_PUT, XTOPT_POINTER(s, timeout)}, 61 {.name = "ctevents", .id = O_CTEVENTS, .type = XTTYPE_STRING}, 62 {.name = "expevents", .id = O_EXPEVENTS, .type = XTTYPE_STRING}, 63 {.name = "zone", .id = O_ZONE, .type = XTTYPE_UINT16, 64 .flags = XTOPT_PUT, XTOPT_POINTER(s, zone)}, 65 XTOPT_TABLEEND, 66}; 67#undef s 68 69struct event_tbl { 70 const char *name; 71 unsigned int event; 72}; 73 74static const struct event_tbl ct_event_tbl[] = { 75 { "new", IPCT_NEW }, 76 { "related", IPCT_RELATED }, 77 { "destroy", IPCT_DESTROY }, 78 { "reply", IPCT_REPLY }, 79 { "assured", IPCT_ASSURED }, 80 { "protoinfo", IPCT_PROTOINFO }, 81 { "helper", IPCT_HELPER }, 82 { "mark", IPCT_MARK }, 83 { "natseqinfo", IPCT_NATSEQADJ }, 84 { "secmark", IPCT_SECMARK }, 85}; 86 87static const struct event_tbl exp_event_tbl[] = { 88 { "new", IPEXP_NEW }, 89}; 90 91static uint32_t ct_parse_events(const struct event_tbl *tbl, unsigned int size, 92 const char *events) 93{ 94 char str[strlen(events) + 1], *e = str, *t; 95 unsigned int mask = 0, i; 96 97 strcpy(str, events); 98 while ((t = strsep(&e, ","))) { 99 for (i = 0; i < size; i++) { 100 if (strcmp(t, tbl[i].name)) 101 continue; 102 mask |= 1 << tbl[i].event; 103 break; 104 } 105 106 if (i == size) 107 xtables_error(PARAMETER_PROBLEM, "Unknown event type \"%s\"", t); 108 } 109 110 return mask; 111} 112 113static void ct_print_events(const char *pfx, const struct event_tbl *tbl, 114 unsigned int size, uint32_t mask) 115{ 116 const char *sep = ""; 117 unsigned int i; 118 119 printf(" %s ", pfx); 120 for (i = 0; i < size; i++) { 121 if (mask & (1 << tbl[i].event)) { 122 printf("%s%s", sep, tbl[i].name); 123 sep = ","; 124 } 125 } 126} 127 128static void ct_parse(struct xt_option_call *cb) 129{ 130 struct xt_ct_target_info *info = cb->data; 131 132 xtables_option_parse(cb); 133 switch (cb->entry->id) { 134 case O_NOTRACK: 135 info->flags |= XT_CT_NOTRACK; 136 break; 137 case O_CTEVENTS: 138 info->ct_events = ct_parse_events(ct_event_tbl, ARRAY_SIZE(ct_event_tbl), cb->arg); 139 break; 140 case O_EXPEVENTS: 141 info->exp_events = ct_parse_events(exp_event_tbl, ARRAY_SIZE(exp_event_tbl), cb->arg); 142 break; 143 } 144} 145 146static void ct_parse_v1(struct xt_option_call *cb) 147{ 148 struct xt_ct_target_info_v1 *info = cb->data; 149 150 xtables_option_parse(cb); 151 switch (cb->entry->id) { 152 case O_NOTRACK: 153 info->flags |= XT_CT_NOTRACK; 154 break; 155 case O_CTEVENTS: 156 info->ct_events = ct_parse_events(ct_event_tbl, 157 ARRAY_SIZE(ct_event_tbl), 158 cb->arg); 159 break; 160 case O_EXPEVENTS: 161 info->exp_events = ct_parse_events(exp_event_tbl, 162 ARRAY_SIZE(exp_event_tbl), 163 cb->arg); 164 break; 165 } 166} 167 168static void ct_print(const void *ip, const struct xt_entry_target *target, int numeric) 169{ 170 const struct xt_ct_target_info *info = 171 (const struct xt_ct_target_info *)target->data; 172 173 printf(" CT"); 174 if (info->flags & XT_CT_NOTRACK) 175 printf(" notrack"); 176 if (info->helper[0]) 177 printf(" helper %s", info->helper); 178 if (info->ct_events) 179 ct_print_events("ctevents", ct_event_tbl, 180 ARRAY_SIZE(ct_event_tbl), info->ct_events); 181 if (info->exp_events) 182 ct_print_events("expevents", exp_event_tbl, 183 ARRAY_SIZE(exp_event_tbl), info->exp_events); 184 if (info->zone) 185 printf("zone %u ", info->zone); 186} 187 188static void 189ct_print_v1(const void *ip, const struct xt_entry_target *target, int numeric) 190{ 191 const struct xt_ct_target_info_v1 *info = 192 (const struct xt_ct_target_info_v1 *)target->data; 193 194 printf(" CT"); 195 if (info->flags & XT_CT_NOTRACK) 196 printf(" notrack"); 197 if (info->helper[0]) 198 printf(" helper %s", info->helper); 199 if (info->timeout[0]) 200 printf(" timeout %s", info->timeout); 201 if (info->ct_events) 202 ct_print_events("ctevents", ct_event_tbl, 203 ARRAY_SIZE(ct_event_tbl), info->ct_events); 204 if (info->exp_events) 205 ct_print_events("expevents", exp_event_tbl, 206 ARRAY_SIZE(exp_event_tbl), info->exp_events); 207 if (info->zone) 208 printf("zone %u ", info->zone); 209} 210 211static void ct_save(const void *ip, const struct xt_entry_target *target) 212{ 213 const struct xt_ct_target_info *info = 214 (const struct xt_ct_target_info *)target->data; 215 216 if (info->flags & XT_CT_NOTRACK) 217 printf(" --notrack"); 218 if (info->helper[0]) 219 printf(" --helper %s", info->helper); 220 if (info->ct_events) 221 ct_print_events("--ctevents", ct_event_tbl, 222 ARRAY_SIZE(ct_event_tbl), info->ct_events); 223 if (info->exp_events) 224 ct_print_events("--expevents", exp_event_tbl, 225 ARRAY_SIZE(exp_event_tbl), info->exp_events); 226 if (info->zone) 227 printf(" --zone %u", info->zone); 228} 229 230static void ct_save_v1(const void *ip, const struct xt_entry_target *target) 231{ 232 const struct xt_ct_target_info_v1 *info = 233 (const struct xt_ct_target_info_v1 *)target->data; 234 235 if (info->flags & XT_CT_NOTRACK) 236 printf(" --notrack"); 237 if (info->helper[0]) 238 printf(" --helper %s", info->helper); 239 if (info->timeout[0]) 240 printf(" --timeout %s", info->timeout); 241 if (info->ct_events) 242 ct_print_events("--ctevents", ct_event_tbl, 243 ARRAY_SIZE(ct_event_tbl), info->ct_events); 244 if (info->exp_events) 245 ct_print_events("--expevents", exp_event_tbl, 246 ARRAY_SIZE(exp_event_tbl), info->exp_events); 247 if (info->zone) 248 printf(" --zone %u", info->zone); 249} 250 251static void notrack_ct0_tg_init(struct xt_entry_target *target) 252{ 253 struct xt_ct_target_info *info = (void *)target->data; 254 255 info->flags = XT_CT_NOTRACK; 256} 257 258static void notrack_ct1_tg_init(struct xt_entry_target *target) 259{ 260 struct xt_ct_target_info_v1 *info = (void *)target->data; 261 262 info->flags = XT_CT_NOTRACK; 263} 264 265static struct xtables_target ct_target_reg[] = { 266 { 267 .family = NFPROTO_UNSPEC, 268 .name = "CT", 269 .version = XTABLES_VERSION, 270 .size = XT_ALIGN(sizeof(struct xt_ct_target_info)), 271 .userspacesize = offsetof(struct xt_ct_target_info, ct), 272 .help = ct_help, 273 .print = ct_print, 274 .save = ct_save, 275 .x6_parse = ct_parse, 276 .x6_options = ct_opts, 277 }, 278 { 279 .family = NFPROTO_UNSPEC, 280 .name = "CT", 281 .revision = 1, 282 .version = XTABLES_VERSION, 283 .size = XT_ALIGN(sizeof(struct xt_ct_target_info_v1)), 284 .userspacesize = offsetof(struct xt_ct_target_info_v1, ct), 285 .help = ct_help_v1, 286 .print = ct_print_v1, 287 .save = ct_save_v1, 288 .x6_parse = ct_parse_v1, 289 .x6_options = ct_opts_v1, 290 }, 291 { 292 .family = NFPROTO_UNSPEC, 293 .name = "NOTRACK", 294 .real_name = "CT", 295 .revision = 0, 296 .version = XTABLES_VERSION, 297 .size = XT_ALIGN(sizeof(struct xt_ct_target_info)), 298 .userspacesize = offsetof(struct xt_ct_target_info, ct), 299 .init = notrack_ct0_tg_init, 300 }, 301 { 302 .family = NFPROTO_UNSPEC, 303 .name = "NOTRACK", 304 .real_name = "CT", 305 .revision = 1, 306 .version = XTABLES_VERSION, 307 .size = XT_ALIGN(sizeof(struct xt_ct_target_info_v1)), 308 .userspacesize = offsetof(struct xt_ct_target_info_v1, ct), 309 .init = notrack_ct1_tg_init, 310 }, 311 { 312 .family = NFPROTO_UNSPEC, 313 .name = "NOTRACK", 314 .revision = 0, 315 .version = XTABLES_VERSION, 316 }, 317}; 318 319void _init(void) 320{ 321 xtables_register_targets(ct_target_reg, ARRAY_SIZE(ct_target_reg)); 322} 323