blob: 7d5c133418c13861e32e616fffbbeabde57d4327 [file] [log] [blame]
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +00001/* Shared library add-on to iptables to add IP range matching support. */
2#include <stdio.h>
3#include <netdb.h>
4#include <string.h>
5#include <stdlib.h>
6#include <getopt.h>
7
8#include <iptables.h>
9#include <linux/netfilter_ipv4/ipt_iprange.h>
10
11/* Function which prints out usage message. */
12static void
13help(void)
14{
15 printf(
16"iprange match v%s options:\n"
17"[!] --src-range ip-ip Match source IP in the specified range\n"
18"[!] --dst-range ip-ip Match destination IP in the specified range\n"
19"\n",
20IPTABLES_VERSION);
21}
22
23static struct option opts[] = {
24 { "src-range", 1, 0, '1' },
25 { "dst-range", 1, 0, '2' },
26 {0}
27};
28
29/* Initialize the match. */
30static void
31init(struct ipt_entry_match *m, unsigned int *nfcache)
32{
33 /* Can't cache this. */
34 *nfcache |= NFC_UNKNOWN;
35}
36
37static void
38parse_iprange(char *arg, struct ipt_iprange *range)
39{
40 char *dash;
41 struct in_addr *ip;
42
43 dash = strchr(arg, '-');
44 if (dash)
45 *dash = '\0';
46
47 ip = dotted_to_addr(arg);
48 if (!ip)
49 exit_error(PARAMETER_PROBLEM, "iprange match: Bad IP address `%s'\n",
50 arg);
51 range->min_ip = ip->s_addr;
52
53 if (dash) {
54 ip = dotted_to_addr(dash+1);
55 if (!ip)
56 exit_error(PARAMETER_PROBLEM, "iprange match: Bad IP address `%s'\n",
57 dash+1);
58 range->max_ip = ip->s_addr;
59 } else
60 range->max_ip = range->min_ip;
61}
62
63/* Function which parses command options; returns true if it
64 ate an option */
65static int
66parse(int c, char **argv, int invert, unsigned int *flags,
67 const struct ipt_entry *entry,
68 unsigned int *nfcache,
69 struct ipt_entry_match **match)
70{
71 struct ipt_iprange_info *info = (struct ipt_iprange_info *)(*match)->data;
72
73 switch (c) {
74 case '1':
75 if (*flags & IPRANGE_SRC)
76 exit_error(PARAMETER_PROBLEM,
77 "iprange match: Only use --src-range ONCE!");
78 *flags |= IPRANGE_SRC;
79
80 info->flags |= IPRANGE_SRC;
81 check_inverse(optarg, &invert, &optind, 0);
82 if (invert) {
83 info->flags |= IPRANGE_SRC_INV;
84 printf("hoho\n");
85 }
86 parse_iprange(optarg, &info->src);
87
88 break;
89
90 case '2':
91 if (*flags & IPRANGE_DST)
92 exit_error(PARAMETER_PROBLEM,
93 "iprange match: Only use --dst-range ONCE!");
94 *flags |= IPRANGE_DST;
95
96 info->flags |= IPRANGE_DST;
97 check_inverse(optarg, &invert, &optind, 0);
98 if (invert)
99 info->flags |= IPRANGE_DST_INV;
100
101 parse_iprange(optarg, &info->dst);
Nicolas Boulianeb9c6ec12004-07-12 07:16:54 +0000102
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000103 break;
104
105 default:
106 return 0;
107 }
108 return 1;
109}
110
111/* Final check; must have specified --src-range or --dst-range. */
112static void
113final_check(unsigned int flags)
114{
115 if (!flags)
116 exit_error(PARAMETER_PROBLEM,
117 "iprange match: You must specify `--src-range' or `--dst-range'");
118}
119
120static void
121print_iprange(const struct ipt_iprange *range)
122{
123 const unsigned char *byte_min, *byte_max;
124
125 byte_min = (const unsigned char *) &(range->min_ip);
126 byte_max = (const unsigned char *) &(range->max_ip);
127 printf("%d.%d.%d.%d-%d.%d.%d.%d ",
128 byte_min[0], byte_min[1], byte_min[2], byte_min[3],
129 byte_max[0], byte_max[1], byte_max[2], byte_max[3]);
130}
131
132/* Prints out the info. */
133static void
134print(const struct ipt_ip *ip,
135 const struct ipt_entry_match *match,
136 int numeric)
137{
138 struct ipt_iprange_info *info = (struct ipt_iprange_info *)match->data;
139
140 if (info->flags & IPRANGE_SRC) {
141 printf("source IP range ");
142 if (info->flags & IPRANGE_SRC_INV)
143 printf("! ");
144 print_iprange(&info->src);
145 }
146 if (info->flags & IPRANGE_DST) {
147 printf("destination IP range ");
148 if (info->flags & IPRANGE_DST_INV)
149 printf("! ");
150 print_iprange(&info->dst);
151 }
152}
153
154/* Saves the union ipt_info in parsable form to stdout. */
155static void
156save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
157{
158 struct ipt_iprange_info *info = (struct ipt_iprange_info *)match->data;
159
160 if (info->flags & IPRANGE_SRC) {
161 if (info->flags & IPRANGE_SRC_INV)
162 printf("! ");
163 printf("--src-range ");
164 print_iprange(&info->src);
165 if (info->flags & IPRANGE_DST)
166 fputc(' ', stdout);
167 }
168 if (info->flags & IPRANGE_DST) {
169 if (info->flags & IPRANGE_DST_INV)
170 printf("! ");
171 printf("--dst-range ");
172 print_iprange(&info->dst);
173 }
174}
175
Pablo Neira8caee8b2004-12-28 13:11:59 +0000176static struct iptables_match iprange = {
177 .next = NULL,
178 .name = "iprange",
179 .version = IPTABLES_VERSION,
180 .size = IPT_ALIGN(sizeof(struct ipt_iprange_info)),
181 .userspacesize = IPT_ALIGN(sizeof(struct ipt_iprange_info)),
182 .help = &help,
183 .init = &init,
184 .parse = &parse,
185 .final_check = &final_check,
186 .print = &print,
187 .save = &save,
188 .extra_opts = opts
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000189};
190
191void _init(void)
192{
193 register_match(&iprange);
194}