1/* Shared library add-on to iptables to add static NAT support.
2   Author: Svenning Soerensen <svenning@post5.tele.dk>
3*/
4#include <stdio.h>
5#include <netdb.h>
6#include <string.h>
7#include <stdlib.h>
8#include <getopt.h>
9#include <xtables.h>
10#include <net/netfilter/nf_nat.h>
11
12#define MODULENAME "NETMAP"
13
14enum {
15	O_TO = 0,
16};
17
18static const struct xt_option_entry NETMAP_opts[] = {
19	{.name = "to", .id = O_TO, .type = XTTYPE_HOSTMASK,
20	 .flags = XTOPT_MAND},
21	XTOPT_TABLEEND,
22};
23
24static void NETMAP_help(void)
25{
26	printf(MODULENAME" target options:\n"
27	       "  --%s address[/mask]\n"
28	       "				Network address to map to.\n\n",
29	       NETMAP_opts[0].name);
30}
31
32static int
33netmask2bits(uint32_t netmask)
34{
35	uint32_t bm;
36	int bits;
37
38	netmask = ntohl(netmask);
39	for (bits = 0, bm = 0x80000000; netmask & bm; netmask <<= 1)
40		bits++;
41	if (netmask)
42		return -1; /* holes in netmask */
43	return bits;
44}
45
46static void NETMAP_init(struct xt_entry_target *t)
47{
48	struct nf_nat_multi_range *mr = (struct nf_nat_multi_range *)t->data;
49
50	/* Actually, it's 0, but it's ignored at the moment. */
51	mr->rangesize = 1;
52}
53
54static void NETMAP_parse(struct xt_option_call *cb)
55{
56	struct nf_nat_multi_range *mr = cb->data;
57	struct nf_nat_range *range = &mr->range[0];
58
59	xtables_option_parse(cb);
60	range->flags |= IP_NAT_RANGE_MAP_IPS;
61	range->min_ip = cb->val.haddr.ip & cb->val.hmask.ip;
62	range->max_ip = range->min_ip | ~cb->val.hmask.ip;
63}
64
65static void NETMAP_print(const void *ip, const struct xt_entry_target *target,
66                         int numeric)
67{
68	const struct nf_nat_multi_range *mr = (const void *)target->data;
69	const struct nf_nat_range *r = &mr->range[0];
70	struct in_addr a;
71	int bits;
72
73	a.s_addr = r->min_ip;
74	printf("%s", xtables_ipaddr_to_numeric(&a));
75	a.s_addr = ~(r->min_ip ^ r->max_ip);
76	bits = netmask2bits(a.s_addr);
77	if (bits < 0)
78		printf("/%s", xtables_ipaddr_to_numeric(&a));
79	else
80		printf("/%d", bits);
81}
82
83static void NETMAP_save(const void *ip, const struct xt_entry_target *target)
84{
85	printf(" --%s ", NETMAP_opts[0].name);
86	NETMAP_print(ip, target, 0);
87}
88
89static struct xtables_target netmap_tg_reg = {
90	.name		= MODULENAME,
91	.version	= XTABLES_VERSION,
92	.family		= NFPROTO_IPV4,
93	.size		= XT_ALIGN(sizeof(struct nf_nat_multi_range)),
94	.userspacesize	= XT_ALIGN(sizeof(struct nf_nat_multi_range)),
95	.help		= NETMAP_help,
96	.init		= NETMAP_init,
97	.x6_parse	= NETMAP_parse,
98	.print		= NETMAP_print,
99	.save		= NETMAP_save,
100	.x6_options	= NETMAP_opts,
101};
102
103void _init(void)
104{
105	xtables_register_target(&netmap_tg_reg);
106}
107