Home | History | Annotate | Download | only in extensions
      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