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 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 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 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 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 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 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 169 void _init(void) 170 { 171 xtables_register_target(&ct_target); 172 } 173