1 /* Shared library add-on to iptables to add ROUTE target support.
2 * Author : Cedric de Launois, <delaunois@info.ucl.ac.be>
11 #include <sys/socket.h>
12 #include <netinet/in.h>
13 #include <arpa/inet.h>
16 #include <linux/netfilter_ipv4/ip_tables.h>
17 #include <linux/netfilter_ipv4/ipt_ROUTE.h>
19 #ifndef XTABLES_VERSION
20 #define XTABLES_VERSION IPTABLES_VERSION
24 #define xtables_target iptables_target
25 #define xtables_register_target register_target
28 /* compile IPT_ROUTE_TEE support even if kernel headers are unpatched */
30 #define IPT_ROUTE_TEE 0x02
33 /* Function which prints out usage message. */
38 "ROUTE target v%s options:\n"
39 " --oif \tifname \t\tRoute packet through `ifname' network interface\n"
40 " --iif \tifname \t\tChange packet's incoming interface to `ifname'\n"
41 " --gw \tip \t\tRoute packet via this gateway `ip'\n"
42 " --continue\t \t\tRoute packet and continue traversing the\n"
43 " \t \t\trules. Not valid with --iif or --tee.\n"
44 " --tee\t \t\tDuplicate packet, route the duplicate,\n"
45 " \t \t\tcontinue traversing with original packet.\n"
46 " \t \t\tNot valid with --iif or --continue.\n"
51 static struct option opts
[] = {
55 { "continue", 0, 0, '4' },
60 /* Initialize the target. */
63 init(struct xt_entry_target
*t
)
65 init(struct ipt_entry_target
*t
, unsigned int *nfcache
)
68 struct ipt_route_target_info
*route_info
=
69 (struct ipt_route_target_info
*)t
->data
;
71 route_info
->oif
[0] = '\0';
72 route_info
->iif
[0] = '\0';
74 route_info
->flags
= 0;
78 #define IPT_ROUTE_OPT_OIF 0x01
79 #define IPT_ROUTE_OPT_IIF 0x02
80 #define IPT_ROUTE_OPT_GW 0x04
81 #define IPT_ROUTE_OPT_CONTINUE 0x08
82 #define IPT_ROUTE_OPT_TEE 0x10
84 /* Function which parses command options; returns true if it
87 parse(int c
, char **argv
, int invert
, unsigned int *flags
,
89 const void *entry
, struct xt_entry_target
**target
)
91 const struct ipt_entry
*entry
, struct ipt_entry_target
**target
)
94 struct ipt_route_target_info
*route_info
=
95 (struct ipt_route_target_info
*)(*target
)->data
;
99 if (*flags
& IPT_ROUTE_OPT_OIF
)
100 exit_error(PARAMETER_PROBLEM
,
101 "Can't specify --oif twice");
103 if (*flags
& IPT_ROUTE_OPT_IIF
)
104 exit_error(PARAMETER_PROBLEM
,
105 "Can't use --oif and --iif together");
107 if (check_inverse(optarg
, &invert
, NULL
, 0))
108 exit_error(PARAMETER_PROBLEM
,
109 "Unexpected `!' after --oif");
111 if (strlen(optarg
) > sizeof(route_info
->oif
) - 1)
112 exit_error(PARAMETER_PROBLEM
,
113 "Maximum interface name length %u",
114 sizeof(route_info
->oif
) - 1);
116 strcpy(route_info
->oif
, optarg
);
117 *flags
|= IPT_ROUTE_OPT_OIF
;
121 if (*flags
& IPT_ROUTE_OPT_IIF
)
122 exit_error(PARAMETER_PROBLEM
,
123 "Can't specify --iif twice");
125 if (*flags
& IPT_ROUTE_OPT_OIF
)
126 exit_error(PARAMETER_PROBLEM
,
127 "Can't use --iif and --oif together");
129 if (check_inverse(optarg
, &invert
, NULL
, 0))
130 exit_error(PARAMETER_PROBLEM
,
131 "Unexpected `!' after --iif");
133 if (strlen(optarg
) > sizeof(route_info
->iif
) - 1)
134 exit_error(PARAMETER_PROBLEM
,
135 "Maximum interface name length %u",
136 sizeof(route_info
->iif
) - 1);
138 strcpy(route_info
->iif
, optarg
);
139 *flags
|= IPT_ROUTE_OPT_IIF
;
143 if (*flags
& IPT_ROUTE_OPT_GW
)
144 exit_error(PARAMETER_PROBLEM
,
145 "Can't specify --gw twice");
147 if (check_inverse(optarg
, &invert
, NULL
, 0))
148 exit_error(PARAMETER_PROBLEM
,
149 "Unexpected `!' after --gw");
151 if (!inet_aton(optarg
, (struct in_addr
*)&route_info
->gw
)) {
152 exit_error(PARAMETER_PROBLEM
,
153 "Invalid IP address %s",
157 *flags
|= IPT_ROUTE_OPT_GW
;
161 if (*flags
& IPT_ROUTE_OPT_CONTINUE
)
162 exit_error(PARAMETER_PROBLEM
,
163 "Can't specify --continue twice");
164 if (*flags
& IPT_ROUTE_OPT_TEE
)
165 exit_error(PARAMETER_PROBLEM
,
166 "Can't specify --continue AND --tee");
168 route_info
->flags
|= IPT_ROUTE_CONTINUE
;
169 *flags
|= IPT_ROUTE_OPT_CONTINUE
;
174 if (*flags
& IPT_ROUTE_OPT_TEE
)
175 exit_error(PARAMETER_PROBLEM
,
176 "Can't specify --tee twice");
177 if (*flags
& IPT_ROUTE_OPT_CONTINUE
)
178 exit_error(PARAMETER_PROBLEM
,
179 "Can't specify --tee AND --continue");
181 route_info
->flags
|= IPT_ROUTE_TEE
;
182 *flags
|= IPT_ROUTE_OPT_TEE
;
195 final_check(unsigned int flags
)
198 exit_error(PARAMETER_PROBLEM
,
199 "ROUTE target: oif, iif or gw option required");
201 if ((flags
& (IPT_ROUTE_OPT_CONTINUE
|IPT_ROUTE_OPT_TEE
)) && (flags
& IPT_ROUTE_OPT_IIF
))
202 exit_error(PARAMETER_PROBLEM
,
203 "ROUTE target: can't continue traversing the rules with iif option");
207 /* Prints out the targinfo. */
210 print(const void *ip
,
211 const struct xt_entry_target
*target
,
213 print(const struct ipt_ip
*ip
,
214 const struct ipt_entry_target
*target
,
218 const struct ipt_route_target_info
*route_info
219 = (const struct ipt_route_target_info
*)target
->data
;
223 if (route_info
->oif
[0])
224 printf("oif:%s ", route_info
->oif
);
226 if (route_info
->iif
[0])
227 printf("iif:%s ", route_info
->iif
);
229 if (route_info
->gw
) {
230 struct in_addr gw
= { route_info
->gw
};
231 printf("gw:%s ", inet_ntoa(gw
));
234 if (route_info
->flags
& IPT_ROUTE_CONTINUE
)
237 if (route_info
->flags
& IPT_ROUTE_TEE
)
245 const struct xt_entry_target
*target
)
247 save(const struct ipt_ip
*ip
,
248 const struct ipt_entry_target
*target
)
251 const struct ipt_route_target_info
*route_info
252 = (const struct ipt_route_target_info
*)target
->data
;
254 if (route_info
->oif
[0])
255 printf("--oif %s ", route_info
->oif
);
257 if (route_info
->iif
[0])
258 printf("--iif %s ", route_info
->iif
);
260 if (route_info
->gw
) {
261 struct in_addr gw
= { route_info
->gw
};
262 printf("--gw %s ", inet_ntoa(gw
));
265 if (route_info
->flags
& IPT_ROUTE_CONTINUE
)
266 printf("--continue ");
268 if (route_info
->flags
& IPT_ROUTE_TEE
)
273 static struct xtables_target route
= {
276 .version
= XTABLES_VERSION
,
277 .size
= IPT_ALIGN(sizeof(struct ipt_route_target_info
)),
278 .userspacesize
= IPT_ALIGN(sizeof(struct ipt_route_target_info
)),
282 .final_check
= &final_check
,
290 xtables_register_target(&route
);