1 /* Shared library add-on to iptables to add ROUTE target support.
2 * Author : Cedric de Launois, <delaunois@info.ucl.ac.be>
12 #include <sys/socket.h>
13 #include <netinet/in.h>
14 #include <arpa/inet.h>
15 #include <linux/netfilter_ipv4/ip_tables.h>
16 #include <linux/netfilter_ipv4/ipt_ROUTE.h>
18 /* Function which prints out usage message. */
23 "ROUTE target v%s options:\n"
24 " --oif \tifname \t\tRoute the packet through `ifname' network interface\n"
25 " --iif \tifname \t\tChange the packet's incoming interface to `ifname'\n"
26 " --gw \tip \t\tRoute the packet via this gateway\n"
27 " --continue\t \t\tRoute the packet and continue traversing the\n"
28 " \t \t\trules. Not valid with --iif.\n"
33 static struct option opts[] = {
37 { "continue", 0, 0, '4' },
41 /* Initialize the target. */
43 init(struct ipt_entry_target *t, unsigned int *nfcache)
45 struct ipt_route_target_info *route_info =
46 (struct ipt_route_target_info*)t->data;
48 route_info->oif[0] = '\0';
49 route_info->iif[0] = '\0';
51 route_info->flags = 0;
55 #define IPT_ROUTE_OPT_OIF 0x01
56 #define IPT_ROUTE_OPT_IIF 0x02
57 #define IPT_ROUTE_OPT_GW 0x04
58 #define IPT_ROUTE_OPT_CONTINUE 0x08
60 /* Function which parses command options; returns true if it
63 parse(int c, char **argv, int invert, unsigned int *flags,
64 const struct ipt_entry *entry,
65 struct ipt_entry_target **target)
67 struct ipt_route_target_info *route_info =
68 (struct ipt_route_target_info*)(*target)->data;
72 if (*flags & IPT_ROUTE_OPT_OIF)
73 exit_error(PARAMETER_PROBLEM,
74 "Can't specify --oif twice");
76 if (*flags & IPT_ROUTE_OPT_IIF)
77 exit_error(PARAMETER_PROBLEM,
78 "Can't use --oif and --iif together");
80 if (check_inverse(optarg, &invert, NULL, 0))
81 exit_error(PARAMETER_PROBLEM,
82 "Unexpected `!' after --oif");
84 if (strlen(optarg) > sizeof(route_info->oif) - 1)
85 exit_error(PARAMETER_PROBLEM,
86 "Maximum interface name length %u",
87 sizeof(route_info->oif) - 1);
89 strcpy(route_info->oif, optarg);
90 *flags |= IPT_ROUTE_OPT_OIF;
94 if (*flags & IPT_ROUTE_OPT_IIF)
95 exit_error(PARAMETER_PROBLEM,
96 "Can't specify --iif twice");
98 if (*flags & IPT_ROUTE_OPT_OIF)
99 exit_error(PARAMETER_PROBLEM,
100 "Can't use --iif and --oif together");
102 if (check_inverse(optarg, &invert, NULL, 0))
103 exit_error(PARAMETER_PROBLEM,
104 "Unexpected `!' after --iif");
106 if (strlen(optarg) > sizeof(route_info->iif) - 1)
107 exit_error(PARAMETER_PROBLEM,
108 "Maximum interface name length %u",
109 sizeof(route_info->iif) - 1);
111 strcpy(route_info->iif, optarg);
112 *flags |= IPT_ROUTE_OPT_IIF;
116 if (*flags & IPT_ROUTE_OPT_GW)
117 exit_error(PARAMETER_PROBLEM,
118 "Can't specify --gw twice");
120 if (check_inverse(optarg, &invert, NULL, 0))
121 exit_error(PARAMETER_PROBLEM,
122 "Unexpected `!' after --gw");
124 if (!inet_aton(optarg, (struct in_addr*)&route_info->gw)) {
125 exit_error(PARAMETER_PROBLEM,
126 "Invalid IP address %s",
130 *flags |= IPT_ROUTE_OPT_GW;
134 if (*flags & IPT_ROUTE_OPT_CONTINUE)
135 exit_error(PARAMETER_PROBLEM,
136 "Can't specify --continue twice");
138 route_info->flags |= IPT_ROUTE_CONTINUE;
139 *flags |= IPT_ROUTE_OPT_CONTINUE;
152 final_check(unsigned int flags)
155 exit_error(PARAMETER_PROBLEM,
156 "ROUTE target: oif, iif or gw option required");
158 if ((flags & IPT_ROUTE_OPT_CONTINUE) && (flags & IPT_ROUTE_OPT_IIF))
159 exit_error(PARAMETER_PROBLEM,
160 "ROUTE target: can't continue traversing the rules with iif option");
164 /* Prints out the targinfo. */
166 print(const struct ipt_ip *ip,
167 const struct ipt_entry_target *target,
170 const struct ipt_route_target_info *route_info
171 = (const struct ipt_route_target_info *)target->data;
175 if (route_info->oif[0])
176 printf("oif:%s ", route_info->oif);
178 if (route_info->iif[0])
179 printf("iif:%s ", route_info->iif);
181 if (route_info->gw) {
182 struct in_addr ip = { route_info->gw };
183 printf("gw:%s ", inet_ntoa(ip));
186 if (route_info->flags & IPT_ROUTE_CONTINUE)
192 static void save(const struct ipt_ip *ip,
193 const struct ipt_entry_target *target)
195 const struct ipt_route_target_info *route_info
196 = (const struct ipt_route_target_info *)target->data;
198 if (route_info->oif[0])
199 printf("--oif %s ", route_info->oif);
201 if (route_info->iif[0])
202 printf("--iif %s ", route_info->iif);
204 if (route_info->gw) {
205 struct in_addr ip = { route_info->gw };
206 printf("--gw %s ", inet_ntoa(ip));
209 if (route_info->flags & IPT_ROUTE_CONTINUE)
210 printf("--continue ");
215 struct iptables_target route
219 IPT_ALIGN(sizeof(struct ipt_route_target_info)),
220 IPT_ALIGN(sizeof(struct ipt_route_target_info)),
232 register_target(&route);