blob: 5906ac47ac9324faf205ab0907b2704ce65d86ed [file] [log] [blame]
Bart De Schuymerff587202005-02-08 20:02:28 +00001/* ebt_nat
2 *
3 * Authors:
4 * Bart De Schuymer <bdschuym@pandora.be>
5 *
6 * June, 2002
7 */
8
Bart De Schuymer1abc55d2002-06-01 19:23:47 +00009#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
Bart De Schuymer41830412002-06-05 19:41:28 +000012#include <netinet/ether.h>
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000013#include <getopt.h>
14#include "../include/ebtables_u.h"
15#include <linux/netfilter_bridge/ebt_nat.h>
16
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000017static int to_source_supplied, to_dest_supplied;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000018
19#define NAT_S '1'
20#define NAT_D '1'
21#define NAT_S_TARGET '2'
22#define NAT_D_TARGET '2'
23static struct option opts_s[] =
24{
25 { "to-source" , required_argument, 0, NAT_S },
26 { "to-src" , required_argument, 0, NAT_S },
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000027 { "snat-target" , required_argument, 0, NAT_S_TARGET },
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000028 { 0 }
29};
30
31static struct option opts_d[] =
32{
33 { "to-destination", required_argument, 0, NAT_D },
34 { "to-dst" , required_argument, 0, NAT_D },
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000035 { "dnat-target" , required_argument, 0, NAT_D_TARGET },
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000036 { 0 }
37};
38
39static void print_help_s()
40{
41 printf(
42 "snat options:\n"
43 " --to-src address : MAC address to map source to\n"
Bart De Schuymerb26649e2002-07-25 14:51:54 +000044 " --snat-target target : ACCEPT, DROP, RETURN or CONTINUE\n");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000045}
46
47static void print_help_d()
48{
49 printf(
50 "dnat options:\n"
51 " --to-dst address : MAC address to map destination to\n"
Bart De Schuymerb26649e2002-07-25 14:51:54 +000052 " --dnat-target target : ACCEPT, DROP, RETURN or CONTINUE\n");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000053}
54
55static void init_s(struct ebt_entry_target *target)
56{
57 struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data;
58
59 to_source_supplied = 0;
60 natinfo->target = EBT_ACCEPT;
Bart De Schuymer2f0d7482003-06-04 06:23:49 +000061 return;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000062}
63
64static void init_d(struct ebt_entry_target *target)
65{
66 struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data;
67
68 to_dest_supplied = 0;
69 natinfo->target = EBT_ACCEPT;
70 return;
71}
72
73#define OPT_SNAT 0x01
74#define OPT_SNAT_TARGET 0x02
75static int parse_s(int c, char **argv, int argc,
76 const struct ebt_u_entry *entry, unsigned int *flags,
77 struct ebt_entry_target **target)
78{
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000079 struct ebt_nat_info *natinfo = (struct ebt_nat_info *)(*target)->data;
Bart De Schuymer41830412002-06-05 19:41:28 +000080 struct ether_addr *addr;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000081
82 switch (c) {
83 case NAT_S:
Bart De Schuymerff587202005-02-08 20:02:28 +000084 ebt_check_option2(flags, OPT_SNAT);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000085 to_source_supplied = 1;
Bart De Schuymer41830412002-06-05 19:41:28 +000086 if (!(addr = ether_aton(optarg)))
Bart De Schuymerff587202005-02-08 20:02:28 +000087 ebt_print_error2("Problem with specified --to-source mac");
Bart De Schuymer41830412002-06-05 19:41:28 +000088 memcpy(natinfo->mac, addr, ETH_ALEN);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000089 break;
90 case NAT_S_TARGET:
Bart De Schuymerff587202005-02-08 20:02:28 +000091 ebt_check_option2(flags, OPT_SNAT_TARGET);
Bart De Schuymer9cfd6542002-08-13 16:08:08 +000092 if (FILL_TARGET(optarg, natinfo->target))
Bart De Schuymerff587202005-02-08 20:02:28 +000093 ebt_print_error2("Illegal --snat-target target");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +000094 break;
95 default:
96 return 0;
97 }
98 return 1;
99}
100
101#define OPT_DNAT 0x01
102#define OPT_DNAT_TARGET 0x02
103static int parse_d(int c, char **argv, int argc,
104 const struct ebt_u_entry *entry, unsigned int *flags,
105 struct ebt_entry_target **target)
106{
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000107 struct ebt_nat_info *natinfo = (struct ebt_nat_info *)(*target)->data;
Bart De Schuymer41830412002-06-05 19:41:28 +0000108 struct ether_addr *addr;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000109
110 switch (c) {
111 case NAT_D:
Bart De Schuymerff587202005-02-08 20:02:28 +0000112 ebt_check_option2(flags, OPT_DNAT);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000113 to_dest_supplied = 1;
Bart De Schuymer41830412002-06-05 19:41:28 +0000114 if (!(addr = ether_aton(optarg)))
Bart De Schuymerff587202005-02-08 20:02:28 +0000115 ebt_print_error2("Problem with specified --to-destination mac");
Bart De Schuymer41830412002-06-05 19:41:28 +0000116 memcpy(natinfo->mac, addr, ETH_ALEN);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000117 break;
118 case NAT_D_TARGET:
Bart De Schuymerff587202005-02-08 20:02:28 +0000119 ebt_check_option2(flags, OPT_DNAT_TARGET);
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000120 if (FILL_TARGET(optarg, natinfo->target))
Bart De Schuymerff587202005-02-08 20:02:28 +0000121 ebt_print_error2("Illegal --dnat-target target");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000122 break;
123 default:
124 return 0;
125 }
126 return 1;
127}
128
129static void final_check_s(const struct ebt_u_entry *entry,
Bart De Schuymer7b9aaeb2002-06-23 20:38:34 +0000130 const struct ebt_entry_target *target, const char *name,
Bart De Schuymerc9b52932002-08-24 13:26:34 +0000131 unsigned int hookmask, unsigned int time)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000132{
Bart De Schuymerb26649e2002-07-25 14:51:54 +0000133 struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data;
134
Bart De Schuymerff587202005-02-08 20:02:28 +0000135 if (BASE_CHAIN && natinfo->target == EBT_RETURN) {
136 ebt_print_error("--snat-target RETURN not allowed on base chain");
137 return;
138 }
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000139 CLEAR_BASE_CHAIN_BIT;
Bart De Schuymerff587202005-02-08 20:02:28 +0000140 if ((hookmask & ~(1 << NF_BR_POST_ROUTING)) || strcmp(name, "nat")) {
Bart De Schuymer64182a32004-01-21 20:39:54 +0000141 ebt_print_error("Wrong chain for snat");
Bart De Schuymerff587202005-02-08 20:02:28 +0000142 } else if (time == 0 && to_source_supplied == 0)
Bart De Schuymer64182a32004-01-21 20:39:54 +0000143 ebt_print_error("No snat address supplied");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000144}
145
146static void final_check_d(const struct ebt_u_entry *entry,
Bart De Schuymer7b9aaeb2002-06-23 20:38:34 +0000147 const struct ebt_entry_target *target, const char *name,
Bart De Schuymerc9b52932002-08-24 13:26:34 +0000148 unsigned int hookmask, unsigned int time)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000149{
Bart De Schuymerb26649e2002-07-25 14:51:54 +0000150 struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data;
151
Bart De Schuymerff587202005-02-08 20:02:28 +0000152 if (BASE_CHAIN && natinfo->target == EBT_RETURN) {
153 ebt_print_error("--dnat-target RETURN not allowed on base chain");
154 return;
155 }
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000156 CLEAR_BASE_CHAIN_BIT;
Bart De Schuymerc9b52932002-08-24 13:26:34 +0000157 if (((hookmask & ~((1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_LOCAL_OUT)))
158 || strcmp(name, "nat")) &&
Bart De Schuymerff587202005-02-08 20:02:28 +0000159 ((hookmask & ~(1 << NF_BR_BROUTING)) || strcmp(name, "broute"))) {
Bart De Schuymer64182a32004-01-21 20:39:54 +0000160 ebt_print_error("Wrong chain for dnat");
Bart De Schuymerff587202005-02-08 20:02:28 +0000161 } if (time == 0 && to_dest_supplied == 0)
Bart De Schuymer64182a32004-01-21 20:39:54 +0000162 ebt_print_error("No dnat address supplied");
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000163}
164
165static void print_s(const struct ebt_u_entry *entry,
166 const struct ebt_entry_target *target)
167{
168 struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000169
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000170 printf("--to-src ");
Bart De Schuymer8339ff12004-01-14 20:05:27 +0000171 ebt_print_mac(natinfo->mac);
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000172 printf(" --snat-target %s", TARGET_NAME(natinfo->target));
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000173}
174
175static void print_d(const struct ebt_u_entry *entry,
176 const struct ebt_entry_target *target)
177{
178 struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data;
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000179
Bart De Schuymer41e8a192002-06-23 08:03:12 +0000180 printf("--to-dst ");
Bart De Schuymer8339ff12004-01-14 20:05:27 +0000181 ebt_print_mac(natinfo->mac);
Bart De Schuymer9cfd6542002-08-13 16:08:08 +0000182 printf(" --dnat-target %s", TARGET_NAME(natinfo->target));
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000183}
184
185static int compare(const struct ebt_entry_target *t1,
186 const struct ebt_entry_target *t2)
187{
188 struct ebt_nat_info *natinfo1 = (struct ebt_nat_info *)t1->data;
189 struct ebt_nat_info *natinfo2 = (struct ebt_nat_info *)t2->data;
190
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000191 return !memcmp(natinfo1->mac, natinfo2->mac, sizeof(natinfo1->mac)) &&
192 natinfo1->target == natinfo2->target;
193}
194
195static struct ebt_u_target snat_target =
196{
Bart De Schuymer7cf1cca2003-08-30 16:20:19 +0000197 .name = EBT_SNAT_TARGET,
198 .size = sizeof(struct ebt_nat_info),
199 .help = print_help_s,
200 .init = init_s,
201 .parse = parse_s,
202 .final_check = final_check_s,
203 .print = print_s,
204 .compare = compare,
205 .extra_ops = opts_s,
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000206};
207
208static struct ebt_u_target dnat_target =
209{
Bart De Schuymer7cf1cca2003-08-30 16:20:19 +0000210 .name = EBT_DNAT_TARGET,
211 .size = sizeof(struct ebt_nat_info),
212 .help = print_help_d,
213 .init = init_d,
214 .parse = parse_d,
215 .final_check = final_check_d,
216 .print = print_d,
217 .compare = compare,
218 .extra_ops = opts_d,
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000219};
220
Bart De Schuymer64182a32004-01-21 20:39:54 +0000221void _init(void)
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000222{
Bart De Schuymer8339ff12004-01-14 20:05:27 +0000223 ebt_register_target(&snat_target);
224 ebt_register_target(&dnat_target);
Bart De Schuymer1abc55d2002-06-01 19:23:47 +0000225}