Busybox: Upgrade to 1.21.1 (stable). lsof active.
[tomato.git] / release / src / router / iptables / extensions / libipt_SAME.c
blob7211f608a2bc1f4b96a5313aa8b69f35b46bf2e2
1 /* Shared library add-on to iptables to add simple non load-balancing SNAT support. */
2 #include <stdio.h>
3 #include <netdb.h>
4 #include <string.h>
5 #include <stdlib.h>
6 #include <getopt.h>
7 #include <iptables.h>
8 #include <linux/netfilter_ipv4/ip_tables.h>
9 #include <linux/netfilter/nf_nat.h>
10 /* For 64bit kernel / 32bit userspace */
11 #include "../include/linux/netfilter_ipv4/ipt_SAME.h"
13 /* Function which prints out usage message. */
14 static void
15 help(void)
17 printf(
18 "SAME v%s options:\n"
19 " --to <ipaddr>-<ipaddr>\n"
20 " Addresses to map source to.\n"
21 " May be specified more than\n"
22 " once for multiple ranges.\n"
23 " --nodst\n"
24 " Don't use destination-ip in\n"
25 " source selection\n"
26 " --random\n"
27 " Randomize source port\n"
29 IPTABLES_VERSION);
32 static struct option opts[] = {
33 { "to", 1, 0, '1' },
34 { "nodst", 0, 0, '2'},
35 { "random", 0, 0, '3' },
36 { 0 }
39 /* Initialize the target. */
40 static void
41 init(struct ipt_entry_target *t, unsigned int *nfcache)
43 struct ipt_same_info *mr = (struct ipt_same_info *)t->data;
45 /* Set default to 0 */
46 mr->rangesize = 0;
47 mr->info = 0;
48 mr->ipnum = 0;
52 /* Parses range of IPs */
53 static void
54 parse_to(char *arg, struct ip_nat_range *range)
56 char *dash;
57 struct in_addr *ip;
59 range->flags |= IP_NAT_RANGE_MAP_IPS;
60 dash = strchr(arg, '-');
62 if (dash)
63 *dash = '\0';
65 ip = dotted_to_addr(arg);
66 if (!ip)
67 exit_error(PARAMETER_PROBLEM, "Bad IP address `%s'\n",
68 arg);
69 range->min_ip = ip->s_addr;
71 if (dash) {
72 ip = dotted_to_addr(dash+1);
73 if (!ip)
74 exit_error(PARAMETER_PROBLEM, "Bad IP address `%s'\n",
75 dash+1);
77 range->max_ip = ip->s_addr;
78 if (dash)
79 if (range->min_ip > range->max_ip)
80 exit_error(PARAMETER_PROBLEM, "Bad IP range `%s-%s'\n",
81 arg, dash+1);
84 #define IPT_SAME_OPT_TO 0x01
85 #define IPT_SAME_OPT_NODST 0x02
86 #define IPT_SAME_OPT_RANDOM 0x04
88 /* Function which parses command options; returns true if it
89 ate an option */
90 static int
91 parse(int c, char **argv, int invert, unsigned int *flags,
92 const struct ipt_entry *entry,
93 struct ipt_entry_target **target)
95 struct ipt_same_info *mr
96 = (struct ipt_same_info *)(*target)->data;
97 int count;
99 switch (c) {
100 case '1':
101 if (mr->rangesize == IPT_SAME_MAX_RANGE)
102 exit_error(PARAMETER_PROBLEM,
103 "Too many ranges specified, maximum "
104 "is %i ranges.\n",
105 IPT_SAME_MAX_RANGE);
106 if (check_inverse(optarg, &invert, NULL, 0))
107 exit_error(PARAMETER_PROBLEM,
108 "Unexpected `!' after --to");
110 parse_to(optarg, &mr->range[mr->rangesize]);
111 /* WTF do we need this for? */
112 if (*flags & IPT_SAME_OPT_RANDOM)
113 mr->range[mr->rangesize].flags
114 |= IP_NAT_RANGE_PROTO_RANDOM;
115 mr->rangesize++;
116 *flags |= IPT_SAME_OPT_TO;
117 break;
119 case '2':
120 if (*flags & IPT_SAME_OPT_NODST)
121 exit_error(PARAMETER_PROBLEM,
122 "Can't specify --nodst twice");
124 mr->info |= IPT_SAME_NODST;
125 *flags |= IPT_SAME_OPT_NODST;
126 break;
128 case '3':
129 *flags |= IPT_SAME_OPT_RANDOM;
130 for (count=0; count < mr->rangesize; count++)
131 mr->range[count].flags |= IP_NAT_RANGE_PROTO_RANDOM;
132 break;
134 default:
135 return 0;
138 return 1;
141 /* Final check; need --to. */
142 static void final_check(unsigned int flags)
144 if (!(flags & IPT_SAME_OPT_TO))
145 exit_error(PARAMETER_PROBLEM,
146 "SAME needs --to");
149 /* Prints out the targinfo. */
150 static void
151 print(const struct ipt_ip *ip,
152 const struct ipt_entry_target *target,
153 int numeric)
155 int count;
156 struct ipt_same_info *mr
157 = (struct ipt_same_info *)target->data;
158 int random = 0;
160 printf("same:");
162 for (count = 0; count < mr->rangesize; count++) {
163 struct ip_nat_range *r = &mr->range[count];
164 struct in_addr a;
166 a.s_addr = r->min_ip;
168 printf("%s", addr_to_dotted(&a));
169 a.s_addr = r->max_ip;
171 if (r->min_ip == r->max_ip)
172 printf(" ");
173 else
174 printf("-%s ", addr_to_dotted(&a));
175 if (r->flags & IP_NAT_RANGE_PROTO_RANDOM)
176 random = 1;
179 if (mr->info & IPT_SAME_NODST)
180 printf("nodst ");
182 if (random)
183 printf("random ");
186 /* Saves the union ipt_targinfo in parsable form to stdout. */
187 static void
188 save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
190 int count;
191 struct ipt_same_info *mr
192 = (struct ipt_same_info *)target->data;
193 int random = 0;
195 for (count = 0; count < mr->rangesize; count++) {
196 struct ip_nat_range *r = &mr->range[count];
197 struct in_addr a;
199 a.s_addr = r->min_ip;
200 printf("--to %s", addr_to_dotted(&a));
201 a.s_addr = r->max_ip;
203 if (r->min_ip == r->max_ip)
204 printf(" ");
205 else
206 printf("-%s ", addr_to_dotted(&a));
207 if (r->flags & IP_NAT_RANGE_PROTO_RANDOM)
208 random = 1;
211 if (mr->info & IPT_SAME_NODST)
212 printf("--nodst ");
214 if (random)
215 printf("--random ");
218 static struct iptables_target same = {
219 .next = NULL,
220 .name = "SAME",
221 .version = IPTABLES_VERSION,
222 .size = IPT_ALIGN(sizeof(struct ipt_same_info)),
223 .userspacesize = IPT_ALIGN(sizeof(struct ipt_same_info)),
224 .help = &help,
225 .init = &init,
226 .parse = &parse,
227 .final_check = &final_check,
228 .print = &print,
229 .save = &save,
230 .extra_opts = opts
233 void _init(void)
235 register_target(&same);