1
/* Shared library add-on to iptables to add DNETMAP support.
2
* (C) 2010 Marek Kierdelewicz <marek@koba.pl>
4
* uses some code from libipt_NETMAP by:
5
* Svenning Soerensen <svenning@post5.tele.dk>
14
#include <net/netfilter/nf_nat.h>
15
#include "xt_DNETMAP.h"
17
#define MODULENAME "DNETMAP"
19
static const struct option DNETMAP_opts[] = {
20
{"prefix", 1, NULL, 'p'},
21
{"reuse", 0, NULL, 'r'},
22
{"ttl", 1, NULL, 't'},
26
static void DNETMAP_help(void)
28
printf(MODULENAME " target options:\n"
29
" --%s address[/mask]\n"
30
" Network subnet to map to. If not specified, all existing prefixes are used.\n"
32
" Reuse entry for given prenat-ip from any prefix despite bindings ttl < 0.\n"
34
" Regenerate bindings ttl value to seconds. If negative value is specified,\n"
35
" bindings ttl is kept unchanged. If not specified then default ttl value (600s)\n"
37
DNETMAP_opts[0].name, DNETMAP_opts[1].name,
38
DNETMAP_opts[2].name);
41
static u_int32_t bits2netmask(int bits)
43
u_int32_t netmask, bm;
45
if (bits >= 32 || bits < 0)
47
for (netmask = 0, bm = 0x80000000; bits; bits--, bm >>= 1)
49
return htonl(netmask);
52
static int netmask2bits(u_int32_t netmask)
57
netmask = ntohl(netmask);
58
for (bits = 0, bm = 0x80000000; netmask & bm; netmask <<= 1)
61
return -1; /* holes in netmask */
65
static void DNETMAP_init(struct xt_entry_target *t)
67
struct xt_DNETMAP_tginfo *tginfo = (void *)&t->data;
68
struct nf_nat_multi_range *mr = &tginfo->prefix;
70
/* Actually, it's 0, but it's ignored at the moment. */
76
/* Parses network address */
77
static void parse_prefix(char *arg, struct nf_nat_range *range)
80
const struct in_addr *ip;
84
range->flags |= IP_NAT_RANGE_MAP_IPS;
85
slash = strchr(arg, '/');
89
ip = xtables_numeric_to_ipaddr(arg);
91
xtables_error(PARAMETER_PROBLEM, "Bad IP address \"%s\"\n",
93
range->min_ip = ip->s_addr;
95
if (strchr(slash + 1, '.')) {
96
ip = xtables_numeric_to_ipmask(slash + 1);
98
xtables_error(PARAMETER_PROBLEM,
99
"Bad netmask \"%s\"\n",
101
netmask = ip->s_addr;
103
if (!xtables_strtoui(slash + 1, NULL, &bits, 0, 32))
104
xtables_error(PARAMETER_PROBLEM,
105
"Bad netmask \"%s\"\n",
107
netmask = bits2netmask(bits);
109
/* Don't allow /0 (/1 is probably insane, too) */
111
xtables_error(PARAMETER_PROBLEM, "Netmask needed\n");
112
/* Mask should be <= then /16 */
114
xtables_error(PARAMETER_PROBLEM,
115
"Max netmask size is /16\n");
119
if (range->min_ip & ~netmask) {
122
xtables_error(PARAMETER_PROBLEM, "Bad network address \"%s\"\n",
125
range->max_ip = range->min_ip | ~netmask;
128
static int DNETMAP_parse(int c, char **argv, int invert, unsigned int *flags,
129
const void *entry, struct xt_entry_target **target)
131
struct xt_DNETMAP_tginfo *tginfo = (void *)(*target)->data;
132
struct nf_nat_multi_range *mr = &tginfo->prefix;
137
xtables_param_act(XTF_ONLY_ONCE, MODULENAME, "--prefix",
138
*flags & XT_DNETMAP_PREFIX);
139
xtables_param_act(XTF_NO_INVERT, MODULENAME, "--prefix",
142
/* TO-DO use xtables_ipparse_any instead? */
143
parse_prefix(optarg, &mr->range[0]);
144
*flags |= XT_DNETMAP_PREFIX;
145
tginfo->flags |= XT_DNETMAP_PREFIX;
148
xtables_param_act(XTF_ONLY_ONCE, MODULENAME, "--reuse",
149
*flags & XT_DNETMAP_REUSE);
150
xtables_param_act(XTF_NO_INVERT, MODULENAME, "--reuse", invert);
151
*flags |= XT_DNETMAP_REUSE;
152
tginfo->flags |= XT_DNETMAP_REUSE;
155
xtables_param_act(XTF_ONLY_ONCE, MODULENAME, "--ttl",
156
*flags & XT_DNETMAP_TTL);
157
xtables_param_act(XTF_NO_INVERT, MODULENAME, "--ttl", invert);
158
*flags |= XT_DNETMAP_TTL;
159
tginfo->flags |= XT_DNETMAP_TTL;
160
tginfo->ttl = strtol(optarg, &end, 10);
169
static void DNETMAP_print_addr(const void *ip,
170
const struct xt_entry_target *target,
173
struct xt_DNETMAP_tginfo *tginfo = (void *)&target->data;
174
const struct nf_nat_multi_range *mr = &tginfo->prefix;
175
const struct nf_nat_range *r = &mr->range[0];
179
a.s_addr = r->min_ip;
180
printf("%s", xtables_ipaddr_to_numeric(&a));
181
a.s_addr = ~(r->min_ip ^ r->max_ip);
182
bits = netmask2bits(a.s_addr);
184
printf("/%s", xtables_ipaddr_to_numeric(&a));
189
static void DNETMAP_print(const void *ip, const struct xt_entry_target *target,
192
struct xt_DNETMAP_tginfo *tginfo = (void *)&target->data;
193
const __u8 *flags = &tginfo->flags;
196
if (*flags & XT_DNETMAP_PREFIX)
197
DNETMAP_print_addr(ip, target, numeric);
201
printf(" reuse %i", (*flags & XT_DNETMAP_REUSE) > 0);
202
if (*flags & XT_DNETMAP_TTL)
203
printf(" ttl %i", tginfo->ttl);
205
printf(" ttl default");
208
static void DNETMAP_save(const void *ip, const struct xt_entry_target *target)
210
struct xt_DNETMAP_tginfo *tginfo = (void *)&target->data;
211
const __u8 *flags = &tginfo->flags;
213
if (*flags & XT_DNETMAP_PREFIX) {
214
printf(" --%s ", DNETMAP_opts[0].name);
215
DNETMAP_print_addr(ip, target, 0);
217
printf(" --reuse %i ", *flags & XT_DNETMAP_REUSE);
219
/* ommited because default value can change as kernel mod param */
220
if (*flags & XT_DNETMAP_TTL)
221
printf(" --ttl %i ", tginfo->ttl);
224
static struct xtables_target dnetmap_tg_reg = {
226
.version = XTABLES_VERSION,
227
.family = NFPROTO_IPV4,
228
.size = XT_ALIGN(sizeof(struct xt_DNETMAP_tginfo)),
229
.userspacesize = XT_ALIGN(sizeof(struct xt_DNETMAP_tginfo)),
230
.help = DNETMAP_help,
231
.init = DNETMAP_init,
232
.parse = DNETMAP_parse,
233
.print = DNETMAP_print,
234
.save = DNETMAP_save,
235
.extra_opts = DNETMAP_opts,
238
static void _init(void)
240
xtables_register_target(&dnetmap_tg_reg);