Home | History | Annotate | Download | only in extensions
      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <stdlib.h>
      4 #include <xtables.h>
      5 #include <net/netfilter/nf_nat.h>
      6 #include <linux/netfilter_ipv4/ipt_SAME.h>
      7 
      8 enum {
      9 	O_TO_ADDR = 0,
     10 	O_NODST,
     11 	O_RANDOM,
     12 	F_RANDOM = 1 << O_RANDOM,
     13 };
     14 
     15 static void SAME_help(void)
     16 {
     17 	printf(
     18 "SAME target options:\n"
     19 " --to <ipaddr>-<ipaddr>\n"
     20 "				Addresses to map source to.\n"
     21 "				 May be specified more than\n"
     22 "				  once for multiple ranges.\n"
     23 " --nodst\n"
     24 "				Don't use destination-ip in\n"
     25 "				           source selection\n"
     26 " --random\n"
     27 "				Randomize source port\n");
     28 }
     29 
     30 static const struct xt_option_entry SAME_opts[] = {
     31 	{.name = "to", .id = O_TO_ADDR, .type = XTTYPE_STRING,
     32 	 .flags = XTOPT_MAND},
     33 	{.name = "nodst", .id = O_NODST, .type = XTTYPE_NONE},
     34 	{.name = "random", .id = O_RANDOM, .type = XTTYPE_NONE},
     35 	XTOPT_TABLEEND,
     36 };
     37 
     38 /* Parses range of IPs */
     39 static void parse_to(const char *orig_arg, struct nf_nat_range *range)
     40 {
     41 	char *dash, *arg;
     42 	const struct in_addr *ip;
     43 
     44 	arg = strdup(orig_arg);
     45 	if (arg == NULL)
     46 		xtables_error(RESOURCE_PROBLEM, "strdup");
     47 	range->flags |= IP_NAT_RANGE_MAP_IPS;
     48 	dash = strchr(arg, '-');
     49 
     50 	if (dash)
     51 		*dash = '\0';
     52 
     53 	ip = xtables_numeric_to_ipaddr(arg);
     54 	if (!ip)
     55 		xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
     56 			   arg);
     57 	range->min_ip = ip->s_addr;
     58 
     59 	if (dash) {
     60 		ip = xtables_numeric_to_ipaddr(dash+1);
     61 		if (!ip)
     62 			xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
     63 				   dash+1);
     64 	}
     65 	range->max_ip = ip->s_addr;
     66 	if (dash)
     67 		if (range->min_ip > range->max_ip)
     68 			xtables_error(PARAMETER_PROBLEM, "Bad IP range \"%s-%s\"\n",
     69 				   arg, dash+1);
     70 	free(arg);
     71 }
     72 
     73 static void SAME_parse(struct xt_option_call *cb)
     74 {
     75 	struct ipt_same_info *mr = cb->data;
     76 	unsigned int count;
     77 
     78 	xtables_option_parse(cb);
     79 	switch (cb->entry->id) {
     80 	case O_TO_ADDR:
     81 		if (mr->rangesize == IPT_SAME_MAX_RANGE)
     82 			xtables_error(PARAMETER_PROBLEM,
     83 				   "Too many ranges specified, maximum "
     84 				   "is %i ranges.\n",
     85 				   IPT_SAME_MAX_RANGE);
     86 		parse_to(cb->arg, &mr->range[mr->rangesize]);
     87 		/* WTF do we need this for? */
     88 		if (cb->xflags & F_RANDOM)
     89 			mr->range[mr->rangesize].flags
     90 				|= IP_NAT_RANGE_PROTO_RANDOM;
     91 		mr->rangesize++;
     92 		break;
     93 	case O_NODST:
     94 		mr->info |= IPT_SAME_NODST;
     95 		break;
     96 	case O_RANDOM:
     97 		for (count=0; count < mr->rangesize; count++)
     98 			mr->range[count].flags |= IP_NAT_RANGE_PROTO_RANDOM;
     99 		break;
    100 	}
    101 }
    102 
    103 static void SAME_print(const void *ip, const struct xt_entry_target *target,
    104                        int numeric)
    105 {
    106 	unsigned int count;
    107 	const struct ipt_same_info *mr = (const void *)target->data;
    108 	int random_selection = 0;
    109 
    110 	printf(" same:");
    111 
    112 	for (count = 0; count < mr->rangesize; count++) {
    113 		const struct nf_nat_range *r = &mr->range[count];
    114 		struct in_addr a;
    115 
    116 		a.s_addr = r->min_ip;
    117 
    118 		printf("%s", xtables_ipaddr_to_numeric(&a));
    119 		a.s_addr = r->max_ip;
    120 
    121 		if (r->min_ip != r->max_ip)
    122 			printf("-%s", xtables_ipaddr_to_numeric(&a));
    123 		if (r->flags & IP_NAT_RANGE_PROTO_RANDOM)
    124 			random_selection = 1;
    125 	}
    126 
    127 	if (mr->info & IPT_SAME_NODST)
    128 		printf(" nodst");
    129 
    130 	if (random_selection)
    131 		printf(" random");
    132 }
    133 
    134 static void SAME_save(const void *ip, const struct xt_entry_target *target)
    135 {
    136 	unsigned int count;
    137 	const struct ipt_same_info *mr = (const void *)target->data;
    138 	int random_selection = 0;
    139 
    140 	for (count = 0; count < mr->rangesize; count++) {
    141 		const struct nf_nat_range *r = &mr->range[count];
    142 		struct in_addr a;
    143 
    144 		a.s_addr = r->min_ip;
    145 		printf(" --to %s", xtables_ipaddr_to_numeric(&a));
    146 		a.s_addr = r->max_ip;
    147 
    148 		if (r->min_ip != r->max_ip)
    149 			printf("-%s", xtables_ipaddr_to_numeric(&a));
    150 		if (r->flags & IP_NAT_RANGE_PROTO_RANDOM)
    151 			random_selection = 1;
    152 	}
    153 
    154 	if (mr->info & IPT_SAME_NODST)
    155 		printf(" --nodst");
    156 
    157 	if (random_selection)
    158 		printf(" --random");
    159 }
    160 
    161 static struct xtables_target same_tg_reg = {
    162 	.name		= "SAME",
    163 	.version	= XTABLES_VERSION,
    164 	.family		= NFPROTO_IPV4,
    165 	.size		= XT_ALIGN(sizeof(struct ipt_same_info)),
    166 	.userspacesize	= XT_ALIGN(sizeof(struct ipt_same_info)),
    167 	.help		= SAME_help,
    168 	.x6_parse	= SAME_parse,
    169 	.print		= SAME_print,
    170 	.save		= SAME_save,
    171 	.x6_options	= SAME_opts,
    172 };
    173 
    174 void _init(void)
    175 {
    176 	xtables_register_target(&same_tg_reg);
    177 }
    178