blob: 4e7ef37a1ef02b82cb11c2350395c8112e322b78 [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>
Harald Weltecf655eb2001-07-28 18:47:11 +000010#include <linux/netfilter_ipv4/ipt_SAME.h>
Martin Josefssonf419f752001-02-19 21:55:27 +000011
Harald Weltecf655eb2001-07-28 18:47:11 +000012#define BREAKUP_IP(x) (x) & 0xFF, ((x)>>8) & 0xFF, ((x)>>16) & 0xFF, (x)>>24
Martin Josefssonf419f752001-02-19 21:55:27 +000013
14/* Function which prints out usage message. */
15static void
16help(void)
17{
18 printf(
19"SAME v%s options:\n"
Harald Welte18f1aff2001-03-25 19:03:23 +000020" --to <ipaddr>-<ipaddr>\n"
Harald Weltecf655eb2001-07-28 18:47:11 +000021" Addresses to map source to.\n"
22" --nodst\n"
23" Don't use destination-ip in\n"
24" source selection\n",
Martin Josefssonf419f752001-02-19 21:55:27 +000025NETFILTER_VERSION);
26}
27
28static struct option opts[] = {
Harald Welte18f1aff2001-03-25 19:03:23 +000029 { "to", 1, 0, '1' },
Harald Weltecf655eb2001-07-28 18:47:11 +000030 { "nodst", 0, 0, '2'},
Martin Josefssonf419f752001-02-19 21:55:27 +000031 { 0 }
32};
33
34/* Initialize the target. */
35static void
36init(struct ipt_entry_target *t, unsigned int *nfcache)
37{
Harald Weltecf655eb2001-07-28 18:47:11 +000038 struct ipt_same_info *mr = (struct ipt_same_info *)t->data;
Martin Josefssonf419f752001-02-19 21:55:27 +000039
40 /* Actually, it's 0, but it's ignored at the moment. */
41 mr->rangesize = 1;
42
Harald Weltecf655eb2001-07-28 18:47:11 +000043 /* Set default info to 0 */
44 mr->info = 0;
45
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, '-');
59 if (dash)
60 *dash = '\0';
61 else
62 exit_error(PARAMETER_PROBLEM, "Bad IP range `%s'\n", arg);
63
64 ip = dotted_to_addr(arg);
65 if (!ip)
66 exit_error(PARAMETER_PROBLEM, "Bad IP address `%s'\n",
67 arg);
68 range->min_ip = ip->s_addr;
69 ip = dotted_to_addr(dash+1);
70 if (!ip)
71 exit_error(PARAMETER_PROBLEM, "Bad IP address `%s'\n",
72 dash+1);
73 range->max_ip = ip->s_addr;
Harald Weltecf655eb2001-07-28 18:47:11 +000074 if (range->min_ip >= range->max_ip)
75 exit_error(PARAMETER_PROBLEM, "Bad IP range `%u.%u.%u.%u-%u.%u.%u.%u'\n", BREAKUP_IP(range->min_ip), BREAKUP_IP(range->max_ip));
Martin Josefssonf419f752001-02-19 21:55:27 +000076}
77
Harald Weltecf655eb2001-07-28 18:47:11 +000078#define IPT_SAME_OPT_TO 0x01
79#define IPT_SAME_OPT_NODST 0x02
80
Martin Josefssonf419f752001-02-19 21:55:27 +000081/* Function which parses command options; returns true if it
82 ate an option */
83static int
84parse(int c, char **argv, int invert, unsigned int *flags,
85 const struct ipt_entry *entry,
86 struct ipt_entry_target **target)
87{
Harald Weltecf655eb2001-07-28 18:47:11 +000088 struct ipt_same_info *mr
89 = (struct ipt_same_info *)(*target)->data;
Martin Josefssonf419f752001-02-19 21:55:27 +000090
91 switch (c) {
92 case '1':
Harald Weltecf655eb2001-07-28 18:47:11 +000093 if (*flags & IPT_SAME_OPT_TO)
94 exit_error(PARAMETER_PROBLEM,
95 "Can't specify --to twice");
96
Martin Josefssonf419f752001-02-19 21:55:27 +000097 if (check_inverse(optarg, &invert))
98 exit_error(PARAMETER_PROBLEM,
Harald Welte18f1aff2001-03-25 19:03:23 +000099 "Unexpected `!' after --to");
Martin Josefssonf419f752001-02-19 21:55:27 +0000100
101 parse_to(optarg, &mr->range[0]);
Harald Weltecf655eb2001-07-28 18:47:11 +0000102 *flags |= IPT_SAME_OPT_TO;
103 break;
104
105 case '2':
106 if (*flags & IPT_SAME_OPT_NODST)
107 exit_error(PARAMETER_PROBLEM,
108 "Can't specify --nodst twice");
109
110 mr->info |= IPT_SAME_NODST;
111 *flags |= IPT_SAME_OPT_NODST;
112 break;
113
Martin Josefssonf419f752001-02-19 21:55:27 +0000114 default:
115 return 0;
116 }
Harald Weltecf655eb2001-07-28 18:47:11 +0000117
118 return 1;
Martin Josefssonf419f752001-02-19 21:55:27 +0000119}
120
Harald Welte18f1aff2001-03-25 19:03:23 +0000121/* Final check; need --to. */
Martin Josefssonf419f752001-02-19 21:55:27 +0000122static void final_check(unsigned int flags)
123{
Harald Weltecf655eb2001-07-28 18:47:11 +0000124 if (!(flags & IPT_SAME_OPT_TO))
Martin Josefssonf419f752001-02-19 21:55:27 +0000125 exit_error(PARAMETER_PROBLEM,
Harald Welte18f1aff2001-03-25 19:03:23 +0000126 "SAME needs --to");
Martin Josefssonf419f752001-02-19 21:55:27 +0000127}
128
129/* Prints out the targinfo. */
130static void
131print(const struct ipt_ip *ip,
132 const struct ipt_entry_target *target,
133 int numeric)
134{
Harald Weltecf655eb2001-07-28 18:47:11 +0000135 struct ipt_same_info *mr
136 = (struct ipt_same_info *)target->data;
Martin Josefssonf419f752001-02-19 21:55:27 +0000137 struct ip_nat_range *r = &mr->range[0];
138 struct in_addr a;
139
140 a.s_addr = r->min_ip;
141
142 printf("same %s", addr_to_dotted(&a));
143 a.s_addr = r->max_ip;
144 printf("-%s ", addr_to_dotted(&a));
Harald Weltecf655eb2001-07-28 18:47:11 +0000145
146 if (mr->info & IPT_SAME_NODST)
147 printf("nodst ");
Martin Josefssonf419f752001-02-19 21:55:27 +0000148}
149
150/* Saves the union ipt_targinfo in parsable form to stdout. */
151static void
152save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
153{
Harald Weltecf655eb2001-07-28 18:47:11 +0000154 struct ipt_same_info *mr
155 = (struct ipt_same_info *)target->data;
Martin Josefssonf419f752001-02-19 21:55:27 +0000156 struct ip_nat_range *r = &mr->range[0];
157 struct in_addr a;
158
159 a.s_addr = r->min_ip;
Harald Welte18f1aff2001-03-25 19:03:23 +0000160 printf("--to %s", addr_to_dotted(&a));
Martin Josefssonf419f752001-02-19 21:55:27 +0000161 a.s_addr = r->max_ip;
162 printf("-%s ", addr_to_dotted(&a));
Harald Weltecf655eb2001-07-28 18:47:11 +0000163
164 if (mr->info & IPT_SAME_NODST)
165 printf("--nodst ");
Martin Josefssonf419f752001-02-19 21:55:27 +0000166}
167
Harald Welte3efb6ea2001-08-06 18:50:21 +0000168static
Martin Josefssonf419f752001-02-19 21:55:27 +0000169struct iptables_target same
170= { NULL,
171 "SAME",
172 NETFILTER_VERSION,
Harald Weltecf655eb2001-07-28 18:47:11 +0000173 IPT_ALIGN(sizeof(struct ipt_same_info)),
174 IPT_ALIGN(sizeof(struct ipt_same_info)),
Martin Josefssonf419f752001-02-19 21:55:27 +0000175 &help,
176 &init,
177 &parse,
178 &final_check,
179 &print,
180 &save,
181 opts
182};
183
184void _init(void)
185{
186 register_target(&same);
187}