Busybox: Upgrade to 1.21.1 (stable). lsof active.
[tomato.git] / release / src / router / iptables / extensions / libipt_ROUTE.c
blob28d143ef192280428964a10d446dc51d340bb32d
1 /* Shared library add-on to iptables to add ROUTE target support.
2 * Author : Cedric de Launois, <delaunois@info.ucl.ac.be>
3 * v 1.11 2004/11/23
4 */
6 #include <stdio.h>
7 #include <string.h>
8 #include <stdlib.h>
9 #include <getopt.h>
10 #include <net/if.h>
11 #include <sys/socket.h>
12 #include <netinet/in.h>
13 #include <arpa/inet.h>
15 #include <iptables.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
21 #endif
23 #ifdef IPT_LIB_DIR
24 #define xtables_target iptables_target
25 #define xtables_register_target register_target
26 #endif
28 /* compile IPT_ROUTE_TEE support even if kernel headers are unpatched */
29 #ifndef IPT_ROUTE_TEE
30 #define IPT_ROUTE_TEE 0x02
31 #endif
33 /* Function which prints out usage message. */
34 static void
35 help(void)
37 printf(
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"
47 "\n",
48 "1.11");
51 static struct option opts[] = {
52 { "oif", 1, 0, '1' },
53 { "iif", 1, 0, '2' },
54 { "gw", 1, 0, '3' },
55 { "continue", 0, 0, '4' },
56 { "tee", 0, 0, '5' },
57 { 0 }
60 /* Initialize the target. */
61 static void
62 #ifdef _XTABLES_H
63 init(struct xt_entry_target *t)
64 #else
65 init(struct ipt_entry_target *t, unsigned int *nfcache)
66 #endif
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';
73 route_info->gw = 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
85 ate an option */
86 static int
87 parse(int c, char **argv, int invert, unsigned int *flags,
88 #ifdef _XTABLES_H
89 const void *entry, struct xt_entry_target **target)
90 #else
91 const struct ipt_entry *entry, struct ipt_entry_target **target)
92 #endif
94 struct ipt_route_target_info *route_info =
95 (struct ipt_route_target_info*)(*target)->data;
97 switch (c) {
98 case '1':
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;
118 break;
120 case '2':
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;
140 break;
142 case '3':
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",
154 optarg);
157 *flags |= IPT_ROUTE_OPT_GW;
158 break;
160 case '4':
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;
171 break;
173 case '5':
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;
184 break;
186 default:
187 return 0;
190 return 1;
194 static void
195 final_check(unsigned int flags)
197 if (!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. */
208 static void
209 #ifdef _XTABLES_H
210 print(const void *ip,
211 const struct xt_entry_target *target,
212 #else
213 print(const struct ipt_ip *ip,
214 const struct ipt_entry_target *target,
215 #endif
216 int numeric)
218 const struct ipt_route_target_info *route_info
219 = (const struct ipt_route_target_info *)target->data;
221 printf("ROUTE ");
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)
235 printf("continue");
237 if (route_info->flags & IPT_ROUTE_TEE)
238 printf("tee");
242 static void
243 #ifdef _XTABLES_H
244 save(const void *ip,
245 const struct xt_entry_target *target)
246 #else
247 save(const struct ipt_ip *ip,
248 const struct ipt_entry_target *target)
249 #endif
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)
269 printf("--tee ");
273 static struct xtables_target route = {
274 .next = NULL,
275 .name = "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)),
279 .help = &help,
280 .init = &init,
281 .parse = &parse,
282 .final_check = &final_check,
283 .print = &print,
284 .save = &save,
285 .extra_opts = opts
288 void _init(void)
290 xtables_register_target(&route);