1 /* Shared library add-on to iptables to add ROUTE v6 target support.
2 * Author : Cedric de Launois, <delaunois@info.ucl.ac.be>
11 #include <sys/types.h>
12 #include <sys/socket.h>
13 #include <arpa/inet.h>
15 #include <ip6tables.h>
16 #include <linux/netfilter_ipv6/ip6_tables.h>
17 #include <linux/netfilter_ipv6/ip6t_ROUTE.h>
19 #ifndef XTABLES_VERSION
20 #define XTABLES_VERSION IPTABLES_VERSION
23 /* compile IP6T_ROUTE_TEE support even if kernel headers are unpatched */
24 #ifndef IP6T_ROUTE_TEE
25 #define IP6T_ROUTE_TEE 0x02
28 /* Function which prints out usage message. */
33 "ROUTE target v%s options:\n"
34 " --oif \tifname \t\tRoute packet through `ifname' network interface\n"
35 " --iif \tifname \t\tChange packet's incoming interface to `ifname'\n"
36 " --gw \tip \t\tRoute packet via this gateway `ip'\n"
37 " --continue\t \t\tRoute packet and continue traversing the\n"
38 " \t \t\trules. Not valid with --iif or --tee.\n"
39 " --tee\t \t\tDuplicate packet, route the duplicate,\n"
40 " \t \t\tcontinue traversing with original packet.\n"
41 " \t \t\tNot valid with --iif or --continue.\n"
46 static struct option opts
[] = {
50 { "continue", 0, 0, '4' },
55 /* Initialize the target. */
58 init(struct xt_entry_target
*t
)
60 init(struct ip6t_entry_target
*t
, unsigned int *nfcache
)
63 struct ip6t_route_target_info
*route_info
=
64 (struct ip6t_route_target_info
*)t
->data
;
66 route_info
->oif
[0] = '\0';
67 route_info
->iif
[0] = '\0';
68 route_info
->gw
[0] = 0;
69 route_info
->gw
[1] = 0;
70 route_info
->gw
[2] = 0;
71 route_info
->gw
[3] = 0;
72 route_info
->flags
= 0;
76 #define IP6T_ROUTE_OPT_OIF 0x01
77 #define IP6T_ROUTE_OPT_IIF 0x02
78 #define IP6T_ROUTE_OPT_GW 0x04
79 #define IP6T_ROUTE_OPT_CONTINUE 0x08
80 #define IP6T_ROUTE_OPT_TEE 0x10
82 /* Function which parses command options; returns true if it
85 parse(int c
, char **argv
, int invert
, unsigned int *flags
,
87 const void *entry
, struct xt_entry_target
**target
)
89 const struct ip6t_entry
*entry
, struct ip6t_entry_target
**target
)
92 struct ip6t_route_target_info
*route_info
=
93 (struct ip6t_route_target_info
*)(*target
)->data
;
97 if (*flags
& IP6T_ROUTE_OPT_OIF
)
98 exit_error(PARAMETER_PROBLEM
,
99 "Can't specify --oif twice");
101 if (check_inverse(optarg
, &invert
, NULL
, 0))
102 exit_error(PARAMETER_PROBLEM
,
103 "Unexpected `!' after --oif");
105 if (strlen(optarg
) > sizeof(route_info
->oif
) - 1)
106 exit_error(PARAMETER_PROBLEM
,
107 "Maximum interface name length %u",
108 sizeof(route_info
->oif
) - 1);
110 strcpy(route_info
->oif
, optarg
);
111 *flags
|= IP6T_ROUTE_OPT_OIF
;
115 exit_error(PARAMETER_PROBLEM
,
116 "--iif option not implemented");
120 if (*flags
& IP6T_ROUTE_OPT_GW
)
121 exit_error(PARAMETER_PROBLEM
,
122 "Can't specify --gw twice");
124 if (check_inverse(optarg
, &invert
, NULL
, 0))
125 exit_error(PARAMETER_PROBLEM
,
126 "Unexpected `!' after --gw");
128 if (!inet_pton(AF_INET6
, optarg
, (struct in6_addr
*)&route_info
->gw
)) {
129 exit_error(PARAMETER_PROBLEM
,
130 "Invalid IPv6 address %s",
134 *flags
|= IP6T_ROUTE_OPT_GW
;
138 if (*flags
& IP6T_ROUTE_OPT_CONTINUE
)
139 exit_error(PARAMETER_PROBLEM
,
140 "Can't specify --continue twice");
141 if (*flags
& IP6T_ROUTE_OPT_TEE
)
142 exit_error(PARAMETER_PROBLEM
,
143 "Can't specify --continue AND --tee");
145 route_info
->flags
|= IP6T_ROUTE_CONTINUE
;
146 *flags
|= IP6T_ROUTE_OPT_CONTINUE
;
151 if (*flags
& IP6T_ROUTE_OPT_TEE
)
152 exit_error(PARAMETER_PROBLEM
,
153 "Can't specify --tee twice");
154 if (*flags
& IP6T_ROUTE_OPT_CONTINUE
)
155 exit_error(PARAMETER_PROBLEM
,
156 "Can't specify --tee AND --continue");
158 route_info
->flags
|= IP6T_ROUTE_TEE
;
159 *flags
|= IP6T_ROUTE_OPT_TEE
;
172 final_check(unsigned int flags
)
175 exit_error(PARAMETER_PROBLEM
,
176 "ROUTE target: oif or gw option required");
180 /* Prints out the targinfo. */
183 print(const void *ip
,
184 const struct xt_entry_target
*target
,
186 print(const struct ip6t_ip6
*ip
,
187 const struct ip6t_entry_target
*target
,
191 const struct ip6t_route_target_info
*route_info
192 = (const struct ip6t_route_target_info
*)target
->data
;
196 if (route_info
->oif
[0])
197 printf("oif:%s ", route_info
->oif
);
199 if (route_info
->gw
[0]
202 || route_info
->gw
[3]) {
203 char address
[INET6_ADDRSTRLEN
];
204 printf("gw:%s ", inet_ntop(AF_INET6
, route_info
->gw
, address
, INET6_ADDRSTRLEN
));
207 if (route_info
->flags
& IP6T_ROUTE_CONTINUE
)
210 if (route_info
->flags
& IP6T_ROUTE_TEE
)
219 const struct xt_entry_target
*target
)
221 save(const struct ip6t_ip6
*ip
,
222 const struct ip6t_entry_target
*target
)
225 const struct ip6t_route_target_info
*route_info
226 = (const struct ip6t_route_target_info
*)target
->data
;
228 if (route_info
->oif
[0])
229 printf("--oif %s ", route_info
->oif
);
231 if (route_info
->gw
[0]
234 || route_info
->gw
[3]) {
235 char address
[INET6_ADDRSTRLEN
];
236 printf("--gw %s ", inet_ntop(AF_INET6
, route_info
->gw
, address
, INET6_ADDRSTRLEN
));
239 if (route_info
->flags
& IP6T_ROUTE_CONTINUE
)
240 printf("--continue ");
242 if (route_info
->flags
& IP6T_ROUTE_TEE
)
247 static struct ip6tables_target route
= {
249 .version
= XTABLES_VERSION
,
250 .size
= IP6T_ALIGN(sizeof(struct ip6t_route_target_info
)),
251 .userspacesize
= IP6T_ALIGN(sizeof(struct ip6t_route_target_info
)),
255 .final_check
= &final_check
,
263 register_target6(&route
);