blob: 52a7e728ef3074c62f0a52e62189846b32f5617d [file] [log] [blame]
Harald Welte18f1aff2001-03-25 19:03:23 +00001/* Shared library add-on to iptables to add simple non load-balancing SNAT support. */
Martin Josefssonf419f752001-02-19 21:55:27 +00002#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>
Martin Josefsson1eb00812004-05-26 15:58:07 +000010/* For 64bit kernel / 32bit userspace */
11#include "../include/linux/netfilter_ipv4/ipt_SAME.h"
Martin Josefssonf419f752001-02-19 21:55:27 +000012
Martin Josefssonf419f752001-02-19 21:55:27 +000013/* Function which prints out usage message. */
14static void
15help(void)
16{
17 printf(
18"SAME v%s options:\n"
Harald Welte18f1aff2001-03-25 19:03:23 +000019" --to <ipaddr>-<ipaddr>\n"
Harald Weltecf655eb2001-07-28 18:47:11 +000020" Addresses to map source to.\n"
Harald Welte05e0b012001-08-26 08:18:25 +000021" May be specified more than\n"
22" once for multiple ranges.\n"
Harald Weltecf655eb2001-07-28 18:47:11 +000023" --nodst\n"
24" Don't use destination-ip in\n"
25" source selection\n",
Harald Welte80fe35d2002-05-29 13:08:15 +000026IPTABLES_VERSION);
Martin Josefssonf419f752001-02-19 21:55:27 +000027}
28
29static struct option opts[] = {
Harald Welte18f1aff2001-03-25 19:03:23 +000030 { "to", 1, 0, '1' },
Harald Weltecf655eb2001-07-28 18:47:11 +000031 { "nodst", 0, 0, '2'},
Martin Josefssonf419f752001-02-19 21:55:27 +000032 { 0 }
33};
34
35/* Initialize the target. */
36static void
37init(struct ipt_entry_target *t, unsigned int *nfcache)
38{
Harald Weltecf655eb2001-07-28 18:47:11 +000039 struct ipt_same_info *mr = (struct ipt_same_info *)t->data;
Martin Josefssonf419f752001-02-19 21:55:27 +000040
Harald Welte05e0b012001-08-26 08:18:25 +000041 /* Set default to 0 */
42 mr->rangesize = 0;
Harald Weltecf655eb2001-07-28 18:47:11 +000043 mr->info = 0;
Harald Welte05e0b012001-08-26 08:18:25 +000044 mr->ipnum = 0;
Harald Weltecf655eb2001-07-28 18:47:11 +000045
Martin Josefssonf419f752001-02-19 21:55:27 +000046 /* Can't cache this */
47 *nfcache |= NFC_UNKNOWN;
48}
49
50/* Parses range of IPs */
51static void
52parse_to(char *arg, struct ip_nat_range *range)
53{
54 char *dash;
55 struct in_addr *ip;
56
57 range->flags |= IP_NAT_RANGE_MAP_IPS;
58 dash = strchr(arg, '-');
Harald Welte05e0b012001-08-26 08:18:25 +000059
Martin Josefssonf419f752001-02-19 21:55:27 +000060 if (dash)
61 *dash = '\0';
Martin Josefssonf419f752001-02-19 21:55:27 +000062
63 ip = dotted_to_addr(arg);
64 if (!ip)
65 exit_error(PARAMETER_PROBLEM, "Bad IP address `%s'\n",
66 arg);
67 range->min_ip = ip->s_addr;
Harald Welte05e0b012001-08-26 08:18:25 +000068
69 if (dash) {
70 ip = dotted_to_addr(dash+1);
71 if (!ip)
72 exit_error(PARAMETER_PROBLEM, "Bad IP address `%s'\n",
73 dash+1);
74 }
Martin Josefssonf419f752001-02-19 21:55:27 +000075 range->max_ip = ip->s_addr;
Harald Welte05e0b012001-08-26 08:18:25 +000076 if (dash)
77 if (range->min_ip > range->max_ip)
78 exit_error(PARAMETER_PROBLEM, "Bad IP range `%s-%s'\n",
79 arg, dash+1);
Martin Josefssonf419f752001-02-19 21:55:27 +000080}
81
Harald Weltecf655eb2001-07-28 18:47:11 +000082#define IPT_SAME_OPT_TO 0x01
83#define IPT_SAME_OPT_NODST 0x02
84
Martin Josefssonf419f752001-02-19 21:55:27 +000085/* Function which parses command options; returns true if it
86 ate an option */
87static int
88parse(int c, char **argv, int invert, unsigned int *flags,
89 const struct ipt_entry *entry,
90 struct ipt_entry_target **target)
91{
Harald Weltecf655eb2001-07-28 18:47:11 +000092 struct ipt_same_info *mr
93 = (struct ipt_same_info *)(*target)->data;
Martin Josefssonf419f752001-02-19 21:55:27 +000094
95 switch (c) {
96 case '1':
Harald Welte05e0b012001-08-26 08:18:25 +000097 if (mr->rangesize == IPT_SAME_MAX_RANGE)
Harald Weltecf655eb2001-07-28 18:47:11 +000098 exit_error(PARAMETER_PROBLEM,
Harald Welte05e0b012001-08-26 08:18:25 +000099 "Too many ranges specified, maximum "
100 "is %i ranges.\n",
101 IPT_SAME_MAX_RANGE);
Harald Welteb77f1da2002-03-14 11:35:58 +0000102 if (check_inverse(optarg, &invert, NULL, 0))
Martin Josefssonf419f752001-02-19 21:55:27 +0000103 exit_error(PARAMETER_PROBLEM,
Harald Welte18f1aff2001-03-25 19:03:23 +0000104 "Unexpected `!' after --to");
Martin Josefssonf419f752001-02-19 21:55:27 +0000105
Harald Welte05e0b012001-08-26 08:18:25 +0000106 parse_to(optarg, &mr->range[mr->rangesize]);
107 mr->rangesize++;
Harald Weltecf655eb2001-07-28 18:47:11 +0000108 *flags |= IPT_SAME_OPT_TO;
109 break;
110
111 case '2':
112 if (*flags & IPT_SAME_OPT_NODST)
113 exit_error(PARAMETER_PROBLEM,
114 "Can't specify --nodst twice");
115
116 mr->info |= IPT_SAME_NODST;
117 *flags |= IPT_SAME_OPT_NODST;
118 break;
119
Martin Josefssonf419f752001-02-19 21:55:27 +0000120 default:
121 return 0;
122 }
Harald Weltecf655eb2001-07-28 18:47:11 +0000123
124 return 1;
Martin Josefssonf419f752001-02-19 21:55:27 +0000125}
126
Harald Welte18f1aff2001-03-25 19:03:23 +0000127/* Final check; need --to. */
Martin Josefssonf419f752001-02-19 21:55:27 +0000128static void final_check(unsigned int flags)
129{
Harald Weltecf655eb2001-07-28 18:47:11 +0000130 if (!(flags & IPT_SAME_OPT_TO))
Martin Josefssonf419f752001-02-19 21:55:27 +0000131 exit_error(PARAMETER_PROBLEM,
Harald Welte18f1aff2001-03-25 19:03:23 +0000132 "SAME needs --to");
Martin Josefssonf419f752001-02-19 21:55:27 +0000133}
134
135/* Prints out the targinfo. */
136static void
137print(const struct ipt_ip *ip,
138 const struct ipt_entry_target *target,
139 int numeric)
140{
Harald Welte05e0b012001-08-26 08:18:25 +0000141 int count;
Harald Weltecf655eb2001-07-28 18:47:11 +0000142 struct ipt_same_info *mr
143 = (struct ipt_same_info *)target->data;
Harald Welte05e0b012001-08-26 08:18:25 +0000144
145 printf("same:");
146
147 for (count = 0; count < mr->rangesize; count++) {
148 struct ip_nat_range *r = &mr->range[count];
149 struct in_addr a;
Martin Josefssonf419f752001-02-19 21:55:27 +0000150
Harald Welte05e0b012001-08-26 08:18:25 +0000151 a.s_addr = r->min_ip;
Martin Josefssonf419f752001-02-19 21:55:27 +0000152
Harald Welte05e0b012001-08-26 08:18:25 +0000153 printf("%s", addr_to_dotted(&a));
154 a.s_addr = r->max_ip;
155
156 if (r->min_ip == r->max_ip)
157 printf(" ");
158 else
159 printf("-%s ", addr_to_dotted(&a));
160 }
Harald Weltecf655eb2001-07-28 18:47:11 +0000161
162 if (mr->info & IPT_SAME_NODST)
163 printf("nodst ");
Martin Josefssonf419f752001-02-19 21:55:27 +0000164}
165
166/* Saves the union ipt_targinfo in parsable form to stdout. */
167static void
168save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
169{
Harald Welte05e0b012001-08-26 08:18:25 +0000170 int count;
Harald Weltecf655eb2001-07-28 18:47:11 +0000171 struct ipt_same_info *mr
172 = (struct ipt_same_info *)target->data;
Martin Josefssonf419f752001-02-19 21:55:27 +0000173
Harald Welte05e0b012001-08-26 08:18:25 +0000174 for (count = 0; count < mr->rangesize; count++) {
175 struct ip_nat_range *r = &mr->range[count];
176 struct in_addr a;
177
178 a.s_addr = r->min_ip;
179 printf("--to %s", addr_to_dotted(&a));
180 a.s_addr = r->max_ip;
181
182 if (r->min_ip == r->max_ip)
183 printf(" ");
184 else
185 printf("-%s ", addr_to_dotted(&a));
186 }
Harald Weltecf655eb2001-07-28 18:47:11 +0000187
188 if (mr->info & IPT_SAME_NODST)
189 printf("--nodst ");
Martin Josefssonf419f752001-02-19 21:55:27 +0000190}
191
Harald Welte3efb6ea2001-08-06 18:50:21 +0000192static
Martin Josefssonf419f752001-02-19 21:55:27 +0000193struct iptables_target same
194= { NULL,
195 "SAME",
Harald Welte80fe35d2002-05-29 13:08:15 +0000196 IPTABLES_VERSION,
Harald Weltecf655eb2001-07-28 18:47:11 +0000197 IPT_ALIGN(sizeof(struct ipt_same_info)),
198 IPT_ALIGN(sizeof(struct ipt_same_info)),
Martin Josefssonf419f752001-02-19 21:55:27 +0000199 &help,
200 &init,
201 &parse,
202 &final_check,
203 &print,
204 &save,
205 opts
206};
207
208void _init(void)
209{
210 register_target(&same);
211}