libxt_CT.c revision d09b6d591ca7d7d7575cb6aa20384c9830f777ab
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 printf(" "); 98} 99 100static int ct_parse(int c, char **argv, int invert, unsigned int *flags, 101 const void *entry, struct xt_entry_target **target) 102{ 103 struct xt_ct_target_info *info = (struct xt_ct_target_info *)(*target)->data; 104 unsigned int zone; 105 106 switch (c) { 107 case CT_OPT_NOTRACK: 108 xtables_param_act(XTF_ONLY_ONCE, "CT", "--notrack", *flags & CT_OPT_NOTRACK); 109 info->flags |= XT_CT_NOTRACK; 110 break; 111 case CT_OPT_HELPER: 112 xtables_param_act(XTF_ONLY_ONCE, "CT", "--helper", *flags & CT_OPT_HELPER); 113 strncpy(info->helper, optarg, sizeof(info->helper)); 114 info->helper[sizeof(info->helper) - 1] = '\0'; 115 break; 116 case CT_OPT_CTEVENTS: 117 xtables_param_act(XTF_ONLY_ONCE, "CT", "--ctevents", *flags & CT_OPT_CTEVENTS); 118 info->ct_events = ct_parse_events(ct_event_tbl, ARRAY_SIZE(ct_event_tbl), optarg); 119 break; 120 case CT_OPT_EXPEVENTS: 121 xtables_param_act(XTF_ONLY_ONCE, "CT", "--expevents", *flags & CT_OPT_EXPEVENTS); 122 info->exp_events = ct_parse_events(exp_event_tbl, ARRAY_SIZE(exp_event_tbl), optarg); 123 break; 124 case CT_OPT_ZONE: 125 xtables_param_act(XTF_ONLY_ONCE, "CT", "--zone", *flags & CT_OPT_ZONE); 126 if (!xtables_strtoui(optarg, NULL, &zone, 0, UINT16_MAX)) 127 xtables_error(PARAMETER_PROBLEM, "Bad zone value \"%s\"", optarg); 128 info->zone = zone; 129 break; 130 } 131 132 *flags |= c; 133 return 1; 134} 135 136static void ct_print(const void *ip, const struct xt_entry_target *target, int numeric) 137{ 138 const struct xt_ct_target_info *info = 139 (const struct xt_ct_target_info *)target->data; 140 141 printf("CT "); 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 156static void ct_save(const void *ip, const struct xt_entry_target *target) 157{ 158 const struct xt_ct_target_info *info = 159 (const struct xt_ct_target_info *)target->data; 160 161 if (info->flags & XT_CT_NOTRACK) 162 printf("--notrack "); 163 if (info->helper[0]) 164 printf("--helper %s ", info->helper); 165 if (info->ct_events) 166 ct_print_events("--ctevents", ct_event_tbl, 167 ARRAY_SIZE(ct_event_tbl), info->ct_events); 168 if (info->exp_events) 169 ct_print_events("--expevents", exp_event_tbl, 170 ARRAY_SIZE(exp_event_tbl), info->exp_events); 171 if (info->zone) 172 printf("--zone %u ", info->zone); 173} 174 175static struct xtables_target ct_target = { 176 .family = NFPROTO_UNSPEC, 177 .name = "CT", 178 .version = XTABLES_VERSION, 179 .size = XT_ALIGN(sizeof(struct xt_ct_target_info)), 180 .userspacesize = offsetof(struct xt_ct_target_info, ct), 181 .help = ct_help, 182 .parse = ct_parse, 183 .print = ct_print, 184 .save = ct_save, 185 .extra_opts = ct_opts, 186}; 187 188void _init(void) 189{ 190 xtables_register_target(&ct_target); 191} 192