libxt_CT.c revision 9f27e6b6f8638bde93e9901e999287ad5118f17c
1#include <stdio.h> 2#include <string.h> 3#include <stdlib.h> 4#include <stddef.h> 5#include <getopt.h> 6#include <xtables.h> 7#include <linux/netfilter/nf_conntrack_common.h> 8#include <linux/netfilter/xt_CT.h> 9 10static void ct_help(void) 11{ 12 printf( 13"CT target options:\n" 14" --notrack Don't track connection\n" 15" --helper name Use conntrack helper 'name' for connection\n" 16" --ctevents event[,event...] Generate specified conntrack events for connection\n" 17" --expevents event[,event...] Generate specified expectation events for connection\n" 18" --zone ID Assign/Lookup connection in zone ID\n" 19 ); 20} 21 22enum ct_options { 23 CT_OPT_NOTRACK = 0x1, 24 CT_OPT_HELPER = 0x2, 25 CT_OPT_CTEVENTS = 0x4, 26 CT_OPT_EXPEVENTS = 0x8, 27 CT_OPT_ZONE = 0x10, 28}; 29 30static const struct option ct_opts[] = { 31 { "notrack", 0, NULL, CT_OPT_NOTRACK }, 32 { "helper", 1, NULL, CT_OPT_HELPER }, 33 { "ctevents", 1, NULL, CT_OPT_CTEVENTS }, 34 { "expevents", 1, NULL, CT_OPT_EXPEVENTS }, 35 { "zone", 1, NULL, CT_OPT_ZONE }, 36 { .name = NULL }, 37}; 38 39struct event_tbl { 40 const char *name; 41 unsigned int event; 42}; 43 44static const struct event_tbl ct_event_tbl[] = { 45 { "new", IPCT_NEW }, 46 { "related", IPCT_RELATED }, 47 { "destroy", IPCT_DESTROY }, 48 { "reply", IPCT_REPLY }, 49 { "assured", IPCT_ASSURED }, 50 { "protoinfo", IPCT_PROTOINFO }, 51 { "helper", IPCT_HELPER }, 52 { "mark", IPCT_MARK }, 53 { "natseqinfo", IPCT_NATSEQADJ }, 54 { "secmark", IPCT_SECMARK }, 55}; 56 57static const struct event_tbl exp_event_tbl[] = { 58 { "new", IPEXP_NEW }, 59}; 60 61static uint32_t ct_parse_events(const struct event_tbl *tbl, unsigned int size, 62 const char *events) 63{ 64 char str[strlen(events) + 1], *e = str, *t; 65 unsigned int mask = 0, i; 66 67 strcpy(str, events); 68 while ((t = strsep(&e, ","))) { 69 for (i = 0; i < size; i++) { 70 if (strcmp(t, tbl->name)) 71 continue; 72 mask |= 1 << tbl->event; 73 break; 74 } 75 76 if (i == size) 77 xtables_error(PARAMETER_PROBLEM, "Unknown event type \"%s\"", t); 78 } 79 80 return mask; 81} 82 83static void ct_print_events(const char *pfx, const struct event_tbl *tbl, 84 unsigned int size, uint32_t mask) 85{ 86 const char *sep = ""; 87 unsigned int i; 88 89 printf("%s ", pfx); 90 for (i = 0; i < size; i++) { 91 if (mask & (1 << tbl[i].event)) { 92 printf("%s%s", sep, tbl[i].name); 93 sep = ","; 94 } 95 } 96 printf(" "); 97} 98 99static int ct_parse(int c, char **argv, int invert, unsigned int *flags, 100 const void *entry, struct xt_entry_target **target) 101{ 102 struct xt_ct_target_info *info = (struct xt_ct_target_info *)(*target)->data; 103 unsigned int zone; 104 105 switch (c) { 106 case CT_OPT_NOTRACK: 107 xtables_param_act(XTF_ONLY_ONCE, "CT", "--notrack", *flags & CT_OPT_NOTRACK); 108 info->flags |= XT_CT_NOTRACK; 109 break; 110 case CT_OPT_HELPER: 111 xtables_param_act(XTF_ONLY_ONCE, "CT", "--helper", *flags & CT_OPT_HELPER); 112 strncpy(info->helper, optarg, sizeof(info->helper)); 113 info->helper[sizeof(info->helper) - 1] = '\0'; 114 break; 115 case CT_OPT_CTEVENTS: 116 xtables_param_act(XTF_ONLY_ONCE, "CT", "--ctevents", *flags & CT_OPT_CTEVENTS); 117 info->ct_events = ct_parse_events(ct_event_tbl, ARRAY_SIZE(ct_event_tbl), optarg); 118 break; 119 case CT_OPT_EXPEVENTS: 120 xtables_param_act(XTF_ONLY_ONCE, "CT", "--expevents", *flags & CT_OPT_EXPEVENTS); 121 info->exp_events = ct_parse_events(exp_event_tbl, ARRAY_SIZE(exp_event_tbl), optarg); 122 break; 123 case CT_OPT_ZONE: 124 xtables_param_act(XTF_ONLY_ONCE, "CT", "--zone", *flags & CT_OPT_ZONE); 125 if (!xtables_strtoui(optarg, NULL, &zone, 0, UINT16_MAX)) 126 xtables_error(PARAMETER_PROBLEM, "Bad zone value \"%s\"", optarg); 127 info->zone = zone; 128 break; 129 default: 130 return 0; 131 } 132 133 *flags |= c; 134 return 1; 135} 136 137static void ct_print(const void *ip, const struct xt_entry_target *target, int numeric) 138{ 139 const struct xt_ct_target_info *info = 140 (const struct xt_ct_target_info *)target->data; 141 142 printf("CT "); 143 if (info->flags & XT_CT_NOTRACK) 144 printf("notrack "); 145 if (info->helper[0]) 146 printf("helper %s ", info->helper); 147 if (info->ct_events) 148 ct_print_events("ctevents", ct_event_tbl, 149 ARRAY_SIZE(ct_event_tbl), info->ct_events); 150 if (info->exp_events) 151 ct_print_events("expevents", exp_event_tbl, 152 ARRAY_SIZE(exp_event_tbl), info->exp_events); 153 if (info->zone) 154 printf("zone %u ", info->zone); 155} 156 157static void ct_save(const void *ip, const struct xt_entry_target *target) 158{ 159 const struct xt_ct_target_info *info = 160 (const struct xt_ct_target_info *)target->data; 161 162 if (info->flags & XT_CT_NOTRACK) 163 printf("--notrack "); 164 if (info->helper[0]) 165 printf("--helper %s ", info->helper); 166 if (info->ct_events) 167 ct_print_events("--ctevents", ct_event_tbl, 168 ARRAY_SIZE(ct_event_tbl), info->ct_events); 169 if (info->exp_events) 170 ct_print_events("--expevents", exp_event_tbl, 171 ARRAY_SIZE(exp_event_tbl), info->exp_events); 172 if (info->zone) 173 printf("--zone %u ", info->zone); 174} 175 176static struct xtables_target ct_target = { 177 .family = NFPROTO_UNSPEC, 178 .name = "CT", 179 .version = XTABLES_VERSION, 180 .size = XT_ALIGN(sizeof(struct xt_ct_target_info)), 181 .userspacesize = offsetof(struct xt_ct_target_info, ct), 182 .help = ct_help, 183 .parse = ct_parse, 184 .print = ct_print, 185 .save = ct_save, 186 .extra_opts = ct_opts, 187}; 188 189void _init(void) 190{ 191 xtables_register_target(&ct_target); 192} 193