libxt_CT.c revision 73866357e4a7a0fdc1b293bf8863fee2bd56da9e
1#include <stdbool.h> 2#include <stdio.h> 3#include <string.h> 4#include <stdlib.h> 5#include <stddef.h> 6#include <getopt.h> 7#include <xtables.h> 8#include <linux/netfilter/nf_conntrack_common.h> 9#include <linux/netfilter/xt_CT.h> 10 11static void ct_help(void) 12{ 13 printf( 14"CT target options:\n" 15" --notrack Don't track connection\n" 16" --helper name Use conntrack helper 'name' for connection\n" 17" --ctevents event[,event...] Generate specified conntrack events for connection\n" 18" --expevents event[,event...] Generate specified expectation events for connection\n" 19" --zone ID Assign/Lookup connection in zone ID\n" 20 ); 21} 22 23enum ct_options { 24 CT_OPT_NOTRACK = 0x1, 25 CT_OPT_HELPER = 0x2, 26 CT_OPT_CTEVENTS = 0x4, 27 CT_OPT_EXPEVENTS = 0x8, 28 CT_OPT_ZONE = 0x10, 29}; 30 31static const struct option ct_opts[] = { 32 {.name = "notrack", .has_arg = false, .val = CT_OPT_NOTRACK}, 33 {.name = "helper", .has_arg = true, .val = CT_OPT_HELPER}, 34 {.name = "ctevents", .has_arg = true, .val = CT_OPT_CTEVENTS}, 35 {.name = "expevents", .has_arg = true, .val = CT_OPT_EXPEVENTS}, 36 {.name = "zone", .has_arg = true, .val = CT_OPT_ZONE}, 37 XT_GETOPT_TABLEEND, 38}; 39 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++) { 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 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 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 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 } 130 131 *flags |= c; 132 return 1; 133} 134 135static void ct_print(const void *ip, const struct xt_entry_target *target, int numeric) 136{ 137 const struct xt_ct_target_info *info = 138 (const struct xt_ct_target_info *)target->data; 139 140 printf(" CT"); 141 if (info->flags & XT_CT_NOTRACK) 142 printf(" notrack"); 143 if (info->helper[0]) 144 printf(" helper %s", info->helper); 145 if (info->ct_events) 146 ct_print_events("ctevents", ct_event_tbl, 147 ARRAY_SIZE(ct_event_tbl), info->ct_events); 148 if (info->exp_events) 149 ct_print_events("expevents", exp_event_tbl, 150 ARRAY_SIZE(exp_event_tbl), info->exp_events); 151 if (info->zone) 152 printf("zone %u ", info->zone); 153} 154 155static void ct_save(const void *ip, const struct xt_entry_target *target) 156{ 157 const struct xt_ct_target_info *info = 158 (const struct xt_ct_target_info *)target->data; 159 160 if (info->flags & XT_CT_NOTRACK) 161 printf(" --notrack"); 162 if (info->helper[0]) 163 printf(" --helper %s", info->helper); 164 if (info->ct_events) 165 ct_print_events("--ctevents", ct_event_tbl, 166 ARRAY_SIZE(ct_event_tbl), info->ct_events); 167 if (info->exp_events) 168 ct_print_events("--expevents", exp_event_tbl, 169 ARRAY_SIZE(exp_event_tbl), info->exp_events); 170 if (info->zone) 171 printf(" --zone %u", info->zone); 172} 173 174static struct xtables_target ct_target = { 175 .family = NFPROTO_UNSPEC, 176 .name = "CT", 177 .version = XTABLES_VERSION, 178 .size = XT_ALIGN(sizeof(struct xt_ct_target_info)), 179 .userspacesize = offsetof(struct xt_ct_target_info, ct), 180 .help = ct_help, 181 .parse = ct_parse, 182 .print = ct_print, 183 .save = ct_save, 184 .extra_opts = ct_opts, 185}; 186 187void _init(void) 188{ 189 xtables_register_target(&ct_target); 190} 191