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 <linux/netfilter/nf_nat.h>
11
12 #define MODULENAME "NETMAP"
13
14 enum {
15 O_TO = 0,
16 };
17
18 static 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
NETMAP_help(void)24 static 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
32 static int
netmask2bits(uint32_t netmask)33 netmask2bits(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
NETMAP_init(struct xt_entry_target * t)46 static void NETMAP_init(struct xt_entry_target *t)
47 {
48 struct nf_nat_ipv4_multi_range_compat *mr = (struct nf_nat_ipv4_multi_range_compat *)t->data;
49
50 /* Actually, it's 0, but it's ignored at the moment. */
51 mr->rangesize = 1;
52 }
53
NETMAP_parse(struct xt_option_call * cb)54 static void NETMAP_parse(struct xt_option_call *cb)
55 {
56 struct nf_nat_ipv4_multi_range_compat *mr = cb->data;
57 struct nf_nat_ipv4_range *range = &mr->range[0];
58
59 xtables_option_parse(cb);
60 range->flags |= NF_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
NETMAP_print(const void * ip,const struct xt_entry_target * target,int numeric)65 static void NETMAP_print(const void *ip, const struct xt_entry_target *target,
66 int numeric)
67 {
68 const struct nf_nat_ipv4_multi_range_compat *mr = (const void *)target->data;
69 const struct nf_nat_ipv4_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
NETMAP_save(const void * ip,const struct xt_entry_target * target)83 static 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
89 static 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_ipv4_multi_range_compat)),
94 .userspacesize = XT_ALIGN(sizeof(struct nf_nat_ipv4_multi_range_compat)),
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
_init(void)103 void _init(void)
104 {
105 xtables_register_target(&netmap_tg_reg);
106 }
107