blob: 05d6db95d1f38ae8580aa997b3ddb38bcbd78e07 [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. */
Jan Engelhardt59d16402007-10-04 16:28:39 +000012static void iprange_help(void)
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +000013{
14 printf(
15"iprange match v%s options:\n"
16"[!] --src-range ip-ip Match source IP in the specified range\n"
17"[!] --dst-range ip-ip Match destination IP in the specified range\n"
18"\n",
19IPTABLES_VERSION);
20}
21
Jan Engelhardt59d16402007-10-04 16:28:39 +000022static const struct option iprange_opts[] = {
Patrick McHardy500f4832007-09-08 15:59:04 +000023 { "src-range", 1, NULL, '1' },
24 { "dst-range", 1, NULL, '2' },
25 { }
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +000026};
27
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +000028static void
29parse_iprange(char *arg, struct ipt_iprange *range)
30{
31 char *dash;
32 struct in_addr *ip;
33
34 dash = strchr(arg, '-');
35 if (dash)
36 *dash = '\0';
37
38 ip = dotted_to_addr(arg);
39 if (!ip)
40 exit_error(PARAMETER_PROBLEM, "iprange match: Bad IP address `%s'\n",
41 arg);
42 range->min_ip = ip->s_addr;
43
44 if (dash) {
45 ip = dotted_to_addr(dash+1);
46 if (!ip)
47 exit_error(PARAMETER_PROBLEM, "iprange match: Bad IP address `%s'\n",
48 dash+1);
49 range->max_ip = ip->s_addr;
50 } else
51 range->max_ip = range->min_ip;
52}
53
54/* Function which parses command options; returns true if it
55 ate an option */
Jan Engelhardt59d16402007-10-04 16:28:39 +000056static int iprange_parse(int c, char **argv, int invert, unsigned int *flags,
57 const void *entry, struct xt_entry_match **match)
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +000058{
59 struct ipt_iprange_info *info = (struct ipt_iprange_info *)(*match)->data;
60
61 switch (c) {
62 case '1':
63 if (*flags & IPRANGE_SRC)
64 exit_error(PARAMETER_PROBLEM,
65 "iprange match: Only use --src-range ONCE!");
66 *flags |= IPRANGE_SRC;
67
68 info->flags |= IPRANGE_SRC;
69 check_inverse(optarg, &invert, &optind, 0);
70 if (invert) {
71 info->flags |= IPRANGE_SRC_INV;
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +000072 }
73 parse_iprange(optarg, &info->src);
74
75 break;
76
77 case '2':
78 if (*flags & IPRANGE_DST)
79 exit_error(PARAMETER_PROBLEM,
80 "iprange match: Only use --dst-range ONCE!");
81 *flags |= IPRANGE_DST;
82
83 info->flags |= IPRANGE_DST;
84 check_inverse(optarg, &invert, &optind, 0);
85 if (invert)
86 info->flags |= IPRANGE_DST_INV;
87
88 parse_iprange(optarg, &info->dst);
Nicolas Boulianeb9c6ec12004-07-12 07:16:54 +000089
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +000090 break;
91
92 default:
93 return 0;
94 }
95 return 1;
96}
97
98/* Final check; must have specified --src-range or --dst-range. */
Jan Engelhardt59d16402007-10-04 16:28:39 +000099static void iprange_check(unsigned int flags)
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000100{
101 if (!flags)
102 exit_error(PARAMETER_PROBLEM,
103 "iprange match: You must specify `--src-range' or `--dst-range'");
104}
105
106static void
107print_iprange(const struct ipt_iprange *range)
108{
109 const unsigned char *byte_min, *byte_max;
110
111 byte_min = (const unsigned char *) &(range->min_ip);
112 byte_max = (const unsigned char *) &(range->max_ip);
113 printf("%d.%d.%d.%d-%d.%d.%d.%d ",
114 byte_min[0], byte_min[1], byte_min[2], byte_min[3],
115 byte_max[0], byte_max[1], byte_max[2], byte_max[3]);
116}
117
118/* Prints out the info. */
Jan Engelhardt59d16402007-10-04 16:28:39 +0000119static void iprange_print(const void *ip, const struct xt_entry_match *match,
120 int numeric)
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000121{
122 struct ipt_iprange_info *info = (struct ipt_iprange_info *)match->data;
123
124 if (info->flags & IPRANGE_SRC) {
125 printf("source IP range ");
126 if (info->flags & IPRANGE_SRC_INV)
127 printf("! ");
128 print_iprange(&info->src);
129 }
130 if (info->flags & IPRANGE_DST) {
131 printf("destination IP range ");
132 if (info->flags & IPRANGE_DST_INV)
133 printf("! ");
134 print_iprange(&info->dst);
135 }
136}
137
138/* Saves the union ipt_info in parsable form to stdout. */
Jan Engelhardt59d16402007-10-04 16:28:39 +0000139static void iprange_save(const void *ip, const struct xt_entry_match *match)
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000140{
141 struct ipt_iprange_info *info = (struct ipt_iprange_info *)match->data;
142
143 if (info->flags & IPRANGE_SRC) {
144 if (info->flags & IPRANGE_SRC_INV)
145 printf("! ");
146 printf("--src-range ");
147 print_iprange(&info->src);
148 if (info->flags & IPRANGE_DST)
149 fputc(' ', stdout);
150 }
151 if (info->flags & IPRANGE_DST) {
152 if (info->flags & IPRANGE_DST_INV)
153 printf("! ");
154 printf("--dst-range ");
155 print_iprange(&info->dst);
156 }
157}
158
Jan Engelhardt59d16402007-10-04 16:28:39 +0000159static struct iptables_match iprange_match = {
Pablo Neira8caee8b2004-12-28 13:11:59 +0000160 .name = "iprange",
161 .version = IPTABLES_VERSION,
162 .size = IPT_ALIGN(sizeof(struct ipt_iprange_info)),
163 .userspacesize = IPT_ALIGN(sizeof(struct ipt_iprange_info)),
Jan Engelhardt59d16402007-10-04 16:28:39 +0000164 .help = iprange_help,
165 .parse = iprange_parse,
166 .final_check = iprange_check,
167 .print = iprange_print,
168 .save = iprange_save,
169 .extra_opts = iprange_opts,
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000170};
171
172void _init(void)
173{
Jan Engelhardt59d16402007-10-04 16:28:39 +0000174 register_match(&iprange_match);
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000175}