1 /* Shared library add-on to iptables to add ROUTE v6 target support.
2 * Author : Cedric de Launois, <delaunois@info.ucl.ac.be>
10 #include <sys/types.h>
11 #include <sys/socket.h>
12 #include <arpa/inet.h>
14 #include <ip6tables.h>
15 #include <linux/netfilter_ipv6/ip6_tables.h>
16 #include <linux/netfilter_ipv6/ip6t_ROUTE.h>
18 /* compile IP6T_ROUTE_TEE support even if kernel headers are unpatched */
19 #ifndef IP6T_ROUTE_TEE
20 #define IP6T_ROUTE_TEE 0x02
23 /* Function which prints out usage message. */
28 "ROUTE target v%s options:\n"
29 " --oif \tifname \t\tRoute the packet through `ifname' network interface\n"
30 " --gw \tip \t\tRoute the packet via this gateway\n"
31 " --continue\t \t\tRoute packet and continue traversing the\n"
32 " \t \t\trules. Not valid with --iif or --tee.\n"
33 " --tee\t \t\tDuplicate packet, route the duplicate,\n"
34 " \t \t\tcontinue traversing with original packet.\n"
35 " \t \t\tNot valid with --iif or --continue.\n"
40 static struct option opts[] = {
44 { "continue", 0, 0, '4' },
49 /* Initialize the target. */
51 init(struct ip6t_entry_target *t, unsigned int *nfcache)
53 struct ip6t_route_target_info *route_info =
54 (struct ip6t_route_target_info*)t->data;
56 route_info->oif[0] = '\0';
57 route_info->iif[0] = '\0';
58 route_info->gw[0] = 0;
59 route_info->gw[1] = 0;
60 route_info->gw[2] = 0;
61 route_info->gw[3] = 0;
62 route_info->flags = 0;
66 #define IP6T_ROUTE_OPT_OIF 0x01
67 #define IP6T_ROUTE_OPT_IIF 0x02
68 #define IP6T_ROUTE_OPT_GW 0x04
69 #define IP6T_ROUTE_OPT_CONTINUE 0x08
70 #define IP6T_ROUTE_OPT_TEE 0x10
72 /* Function which parses command options; returns true if it
75 parse(int c, char **argv, int invert, unsigned int *flags,
76 const struct ip6t_entry *entry,
77 struct ip6t_entry_target **target)
79 struct ip6t_route_target_info *route_info =
80 (struct ip6t_route_target_info*)(*target)->data;
84 if (*flags & IP6T_ROUTE_OPT_OIF)
85 exit_error(PARAMETER_PROBLEM,
86 "Can't specify --oif twice");
88 if (check_inverse(optarg, &invert, NULL, 0))
89 exit_error(PARAMETER_PROBLEM,
90 "Unexpected `!' after --oif");
92 if (strlen(optarg) > sizeof(route_info->oif) - 1)
93 exit_error(PARAMETER_PROBLEM,
94 "Maximum interface name length %u",
95 sizeof(route_info->oif) - 1);
97 strcpy(route_info->oif, optarg);
98 *flags |= IP6T_ROUTE_OPT_OIF;
102 exit_error(PARAMETER_PROBLEM,
103 "--iif option not implemented");
107 if (*flags & IP6T_ROUTE_OPT_GW)
108 exit_error(PARAMETER_PROBLEM,
109 "Can't specify --gw twice");
111 if (check_inverse(optarg, &invert, NULL, 0))
112 exit_error(PARAMETER_PROBLEM,
113 "Unexpected `!' after --gw");
115 if (!inet_pton(AF_INET6, optarg, (struct in6_addr*)&route_info->gw)) {
116 exit_error(PARAMETER_PROBLEM,
117 "Invalid IPv6 address %s",
121 *flags |= IP6T_ROUTE_OPT_GW;
125 if (*flags & IP6T_ROUTE_OPT_CONTINUE)
126 exit_error(PARAMETER_PROBLEM,
127 "Can't specify --continue twice");
128 if (*flags & IP6T_ROUTE_OPT_TEE)
129 exit_error(PARAMETER_PROBLEM,
130 "Can't specify --continue AND --tee");
132 route_info->flags |= IP6T_ROUTE_CONTINUE;
133 *flags |= IP6T_ROUTE_OPT_CONTINUE;
138 if (*flags & IP6T_ROUTE_OPT_TEE)
139 exit_error(PARAMETER_PROBLEM,
140 "Can't specify --tee twice");
141 if (*flags & IP6T_ROUTE_OPT_CONTINUE)
142 exit_error(PARAMETER_PROBLEM,
143 "Can't specify --tee AND --continue");
145 route_info->flags |= IP6T_ROUTE_TEE;
146 *flags |= IP6T_ROUTE_OPT_TEE;
159 final_check(unsigned int flags)
162 exit_error(PARAMETER_PROBLEM,
163 "ROUTE target: oif or gw option required");
167 /* Prints out the targinfo. */
169 print(const struct ip6t_ip6 *ip,
170 const struct ip6t_entry_target *target,
173 const struct ip6t_route_target_info *route_info
174 = (const struct ip6t_route_target_info *)target->data;
178 if (route_info->oif[0])
179 printf("oif:%s ", route_info->oif);
181 if (route_info->gw[0]
184 || route_info->gw[3]) {
185 char address[INET6_ADDRSTRLEN];
186 printf("gw:%s ", inet_ntop(AF_INET6, route_info->gw, address, INET6_ADDRSTRLEN));
189 if (route_info->flags & IP6T_ROUTE_CONTINUE)
192 if (route_info->flags & IP6T_ROUTE_TEE)
198 static void save(const struct ip6t_ip6 *ip,
199 const struct ip6t_entry_target *target)
201 const struct ip6t_route_target_info *route_info
202 = (const struct ip6t_route_target_info *)target->data;
204 if (route_info->oif[0])
205 printf("--oif %s ", route_info->oif);
207 if (route_info->gw[0]
210 || route_info->gw[3]) {
211 char address[INET6_ADDRSTRLEN];
212 printf("--gw %s ", inet_ntop(AF_INET6, route_info->gw, address, INET6_ADDRSTRLEN));
215 if (route_info->flags & IP6T_ROUTE_CONTINUE)
216 printf("--continue ");
218 if (route_info->flags & IP6T_ROUTE_TEE)
223 static struct ip6tables_target route = {
225 .version = IPTABLES_VERSION,
226 .size = IP6T_ALIGN(sizeof(struct ip6t_route_target_info)),
227 .userspacesize = IP6T_ALIGN(sizeof(struct ip6t_route_target_info)),
231 .final_check = &final_check,
239 register_target6(&route);