Home | History | Annotate | Download | only in extensions
      1 /*
      2  * Copyright (c) 2011 Patrick McHardy <kaber (at) trash.net>
      3  *
      4  * Based on Svenning Soerensen's IPv4 NETMAP target. Development of IPv6 NAT
      5  * funded by Astaro.
      6  */
      7 
      8 #include <stdio.h>
      9 #include <netdb.h>
     10 #include <string.h>
     11 #include <stdlib.h>
     12 #include <getopt.h>
     13 #include <xtables.h>
     14 #include <libiptc/libip6tc.h>
     15 #include <linux/netfilter/nf_nat.h>
     16 
     17 #define MODULENAME "NETMAP"
     18 
     19 enum {
     20 	O_TO = 0,
     21 };
     22 
     23 static const struct xt_option_entry NETMAP_opts[] = {
     24 	{.name = "to", .id = O_TO, .type = XTTYPE_HOSTMASK,
     25 	 .flags = XTOPT_MAND},
     26 	XTOPT_TABLEEND,
     27 };
     28 
     29 static void NETMAP_help(void)
     30 {
     31 	printf(MODULENAME" target options:\n"
     32 	       "  --%s address[/mask]\n"
     33 	       "				Network address to map to.\n\n",
     34 	       NETMAP_opts[0].name);
     35 }
     36 
     37 static void NETMAP_parse(struct xt_option_call *cb)
     38 {
     39 	struct nf_nat_range *range = cb->data;
     40 	unsigned int i;
     41 
     42 	xtables_option_parse(cb);
     43 	range->flags |= NF_NAT_RANGE_MAP_IPS;
     44 	for (i = 0; i < 4; i++) {
     45 		range->min_addr.ip6[i] = cb->val.haddr.ip6[i] &
     46 					 cb->val.hmask.ip6[i];
     47 		range->max_addr.ip6[i] = range->min_addr.ip6[i] |
     48 					 ~cb->val.hmask.ip6[i];
     49 	}
     50 }
     51 
     52 static void NETMAP_print(const void *ip, const struct xt_entry_target *target,
     53                          int numeric)
     54 {
     55 	const struct nf_nat_range *r = (const void *)target->data;
     56 	struct in6_addr a;
     57 	unsigned int i;
     58 	int bits;
     59 
     60 	a = r->min_addr.in6;
     61 	printf("%s", xtables_ip6addr_to_numeric(&a));
     62 	for (i = 0; i < 4; i++)
     63 		a.s6_addr32[i] = ~(r->min_addr.ip6[i] ^ r->max_addr.ip6[i]);
     64 	bits = xtables_ip6mask_to_cidr(&a);
     65 	if (bits < 0)
     66 		printf("/%s", xtables_ip6addr_to_numeric(&a));
     67 	else
     68 		printf("/%d", bits);
     69 }
     70 
     71 static void NETMAP_save(const void *ip, const struct xt_entry_target *target)
     72 {
     73 	printf(" --%s ", NETMAP_opts[0].name);
     74 	NETMAP_print(ip, target, 0);
     75 }
     76 
     77 static struct xtables_target netmap_tg_reg = {
     78 	.name		= MODULENAME,
     79 	.version	= XTABLES_VERSION,
     80 	.family		= NFPROTO_IPV6,
     81 	.size		= XT_ALIGN(sizeof(struct nf_nat_range)),
     82 	.userspacesize	= XT_ALIGN(sizeof(struct nf_nat_range)),
     83 	.help		= NETMAP_help,
     84 	.x6_parse	= NETMAP_parse,
     85 	.print		= NETMAP_print,
     86 	.save		= NETMAP_save,
     87 	.x6_options	= NETMAP_opts,
     88 };
     89 
     90 void _init(void)
     91 {
     92 	xtables_register_target(&netmap_tg_reg);
     93 }
     94