iptables-1.3.2-20050720
[iptables.git] / extensions / libipt_SAME.c
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_ipv4/ip_nat_rule.h>
10 /* For 64bit kernel / 32bit userspace */
11 #include "../include/linux/netfilter_ipv4/ipt_SAME.h"
12
13 /* Function which prints out usage message. */
14 static void
15 help(void)
16 {
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 IPTABLES_VERSION);
27 }
28
29 static struct option opts[] = {
30         { "to", 1, 0, '1' },
31         { "nodst", 0, 0, '2'},
32         { 0 }
33 };
34
35 /* Initialize the target. */
36 static void
37 init(struct ipt_entry_target *t, unsigned int *nfcache)
38 {
39         struct ipt_same_info *mr = (struct ipt_same_info *)t->data;
40
41         /* Set default to 0 */
42         mr->rangesize = 0;
43         mr->info = 0;
44         mr->ipnum = 0;
45         
46 }
47
48 /* Parses range of IPs */
49 static void
50 parse_to(char *arg, struct ip_nat_range *range)
51 {
52         char *dash;
53         struct in_addr *ip;
54
55         range->flags |= IP_NAT_RANGE_MAP_IPS;
56         dash = strchr(arg, '-');
57
58         if (dash)
59                 *dash = '\0';
60
61         ip = dotted_to_addr(arg);
62         if (!ip)
63                 exit_error(PARAMETER_PROBLEM, "Bad IP address `%s'\n",
64                            arg);
65         range->min_ip = ip->s_addr;
66
67         if (dash) {
68                 ip = dotted_to_addr(dash+1);
69                 if (!ip)
70                         exit_error(PARAMETER_PROBLEM, "Bad IP address `%s'\n",
71                                    dash+1);
72         }
73         range->max_ip = ip->s_addr;
74         if (dash)
75                 if (range->min_ip > range->max_ip)
76                         exit_error(PARAMETER_PROBLEM, "Bad IP range `%s-%s'\n", 
77                                    arg, dash+1);
78 }
79
80 #define IPT_SAME_OPT_TO                 0x01
81 #define IPT_SAME_OPT_NODST              0x02
82
83 /* Function which parses command options; returns true if it
84    ate an option */
85 static int
86 parse(int c, char **argv, int invert, unsigned int *flags,
87       const struct ipt_entry *entry,
88       struct ipt_entry_target **target)
89 {
90         struct ipt_same_info *mr
91                 = (struct ipt_same_info *)(*target)->data;
92
93         switch (c) {
94         case '1':
95                 if (mr->rangesize == IPT_SAME_MAX_RANGE)
96                         exit_error(PARAMETER_PROBLEM,
97                                    "Too many ranges specified, maximum "
98                                    "is %i ranges.\n",
99                                    IPT_SAME_MAX_RANGE);
100                 if (check_inverse(optarg, &invert, NULL, 0))
101                         exit_error(PARAMETER_PROBLEM,
102                                    "Unexpected `!' after --to");
103
104                 parse_to(optarg, &mr->range[mr->rangesize]);
105                 mr->rangesize++;
106                 *flags |= IPT_SAME_OPT_TO;
107                 break;
108                 
109         case '2':
110                 if (*flags & IPT_SAME_OPT_NODST)
111                         exit_error(PARAMETER_PROBLEM,
112                                    "Can't specify --nodst twice");
113                 
114                 mr->info |= IPT_SAME_NODST;
115                 *flags |= IPT_SAME_OPT_NODST;
116                 break;
117                 
118         default:
119                 return 0;
120         }
121         
122         return 1;
123 }
124
125 /* Final check; need --to. */
126 static void final_check(unsigned int flags)
127 {
128         if (!(flags & IPT_SAME_OPT_TO))
129                 exit_error(PARAMETER_PROBLEM,
130                            "SAME needs --to");
131 }
132
133 /* Prints out the targinfo. */
134 static void
135 print(const struct ipt_ip *ip,
136       const struct ipt_entry_target *target,
137       int numeric)
138 {
139         int count;
140         struct ipt_same_info *mr
141                 = (struct ipt_same_info *)target->data;
142         
143         printf("same:");
144         
145         for (count = 0; count < mr->rangesize; count++) {
146                 struct ip_nat_range *r = &mr->range[count];
147                 struct in_addr a;
148
149                 a.s_addr = r->min_ip;
150
151                 printf("%s", addr_to_dotted(&a));
152                 a.s_addr = r->max_ip;
153                 
154                 if (r->min_ip == r->max_ip)
155                         printf(" ");
156                 else
157                         printf("-%s ", addr_to_dotted(&a));
158         }
159         
160         if (mr->info & IPT_SAME_NODST)
161                 printf("nodst ");
162 }
163
164 /* Saves the union ipt_targinfo in parsable form to stdout. */
165 static void
166 save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
167 {
168         int count;
169         struct ipt_same_info *mr
170                 = (struct ipt_same_info *)target->data;
171
172         for (count = 0; count < mr->rangesize; count++) {
173                 struct ip_nat_range *r = &mr->range[count];
174                 struct in_addr a;
175
176                 a.s_addr = r->min_ip;
177                 printf("--to %s", addr_to_dotted(&a));
178                 a.s_addr = r->max_ip;
179
180                 if (r->min_ip == r->max_ip)
181                         printf(" ");
182                 else
183                         printf("-%s ", addr_to_dotted(&a));
184         }
185         
186         if (mr->info & IPT_SAME_NODST)
187                 printf("--nodst ");
188 }
189
190 static struct iptables_target same = {
191         .next           = NULL,
192         .name           = "SAME",
193         .version        = IPTABLES_VERSION,
194         .size           = IPT_ALIGN(sizeof(struct ipt_same_info)),
195         .userspacesize  = IPT_ALIGN(sizeof(struct ipt_same_info)),
196         .help           = &help,
197         .init           = &init,
198         .parse          = &parse,
199         .final_check    = &final_check,
200         .print          = &print,
201         .save           = &save,
202         .extra_opts     = opts
203 };
204
205 void _init(void)
206 {
207         register_target(&same);
208 }