1 /* Shared library add-on to iptables to add static NAT support.
2 Author: Svenning Soerensen <svenning@post5.tele.dk>
11 #include <linux/netfilter_ipv4/ip_tables.h>
12 #include <linux/netfilter_ipv4/ip_nat_rule.h>
14 #define MODULENAME "NETMAP"
16 static struct option opts
[] = {
21 /* Function which prints out usage message. */
25 printf(MODULENAME
" v%s options:\n"
26 " --%s address[/mask]\n"
27 " Network address to map to.\n\n",
28 IPTABLES_VERSION
, opts
[0].name
);
32 bits2netmask(int bits
)
34 u_int32_t netmask
, bm
;
36 if (bits
>= 32 || bits
< 0)
38 for (netmask
= 0, bm
= 0x80000000; bits
; bits
--, bm
>>= 1)
40 return htonl(netmask
);
44 netmask2bits(u_int32_t netmask
)
49 netmask
= ntohl(netmask
);
50 for (bits
= 0, bm
= 0x80000000; netmask
& bm
; netmask
<<= 1)
53 return -1; /* holes in netmask */
57 /* Initialize the target. */
59 init(struct ipt_entry_target
*t
, unsigned int *nfcache
)
61 struct ip_nat_multi_range
*mr
= (struct ip_nat_multi_range
*)t
->data
;
63 /* Actually, it's 0, but it's ignored at the moment. */
68 /* Parses network address */
70 parse_to(char *arg
, struct ip_nat_range
*range
)
77 range
->flags
|= IP_NAT_RANGE_MAP_IPS
;
78 slash
= strchr(arg
, '/');
82 ip
= dotted_to_addr(arg
);
84 exit_error(PARAMETER_PROBLEM
, "Bad IP address `%s'\n",
86 range
->min_ip
= ip
->s_addr
;
88 if (strchr(slash
+1, '.')) {
89 ip
= dotted_to_mask(slash
+1);
91 exit_error(PARAMETER_PROBLEM
, "Bad netmask `%s'\n",
96 if (string_to_number(slash
+1, 0, 32, &bits
) == -1)
97 exit_error(PARAMETER_PROBLEM
, "Bad netmask `%s'\n",
99 netmask
= bits2netmask(bits
);
101 /* Don't allow /0 (/1 is probably insane, too) */
103 exit_error(PARAMETER_PROBLEM
, "Netmask needed\n");
108 if (range
->min_ip
& ~netmask
) {
111 exit_error(PARAMETER_PROBLEM
, "Bad network address `%s'\n",
114 range
->max_ip
= range
->min_ip
| ~netmask
;
117 /* Function which parses command options; returns true if it
120 parse(int c
, char **argv
, int invert
, unsigned int *flags
,
121 const struct ipt_entry
*entry
,
122 struct ipt_entry_target
**target
)
124 struct ip_nat_multi_range
*mr
125 = (struct ip_nat_multi_range
*)(*target
)->data
;
129 if (check_inverse(optarg
, &invert
, NULL
, 0))
130 exit_error(PARAMETER_PROBLEM
,
131 "Unexpected `!' after --%s", opts
[0].name
);
133 parse_to(optarg
, &mr
->range
[0]);
142 /* Final check; need --to */
143 static void final_check(unsigned int flags
)
146 exit_error(PARAMETER_PROBLEM
,
147 MODULENAME
" needs --%s", opts
[0].name
);
150 /* Prints out the targinfo. */
152 print(const struct ipt_ip
*ip
,
153 const struct ipt_entry_target
*target
,
156 struct ip_nat_multi_range
*mr
157 = (struct ip_nat_multi_range
*)target
->data
;
158 struct ip_nat_range
*r
= &mr
->range
[0];
162 a
.s_addr
= r
->min_ip
;
163 printf("%s", addr_to_dotted(&a
));
164 a
.s_addr
= ~(r
->min_ip
^ r
->max_ip
);
165 bits
= netmask2bits(a
.s_addr
);
167 printf("/%s", addr_to_dotted(&a
));
172 /* Saves the targinfo in parsable form to stdout. */
174 save(const struct ipt_ip
*ip
, const struct ipt_entry_target
*target
)
176 printf("--%s ", opts
[0].name
);
177 print(ip
, target
, 0);
180 static struct iptables_target target_module
= {
183 .version
= IPTABLES_VERSION
,
184 .size
= IPT_ALIGN(sizeof(struct ip_nat_multi_range
)),
185 .userspacesize
= IPT_ALIGN(sizeof(struct ip_nat_multi_range
)),
189 .final_check
= &final_check
,
197 register_target(&target_module
);