blob: 65a15c943469a1847175ad2a0e56687312ef0722 [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
Jan Engelhardt41daaa02008-01-20 13:42:43 +000011static void iprange_mt_help(void)
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +000012{
13 printf(
Jan Engelhardt41daaa02008-01-20 13:42:43 +000014"iprange match options:\n"
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +000015"[!] --src-range ip-ip Match source IP in the specified range\n"
16"[!] --dst-range ip-ip Match destination IP in the specified range\n"
Jan Engelhardt41daaa02008-01-20 13:42:43 +000017"\n");
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +000018}
19
Jan Engelhardt41daaa02008-01-20 13:42:43 +000020static const struct option iprange_mt_opts[] = {
21 {.name = "src-range", .has_arg = true, .val = '1'},
22 {.name = "dst-range", .has_arg = true, .val = '2'},
23 {},
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +000024};
25
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +000026static void
27parse_iprange(char *arg, struct ipt_iprange *range)
28{
29 char *dash;
Jan Engelhardtbd943842008-01-20 13:38:08 +000030 const struct in_addr *ip;
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +000031
32 dash = strchr(arg, '-');
Jan Engelhardt41daaa02008-01-20 13:42:43 +000033 if (dash != NULL)
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +000034 *dash = '\0';
Jan Engelhardt41daaa02008-01-20 13:42:43 +000035
Jan Engelhardtbd943842008-01-20 13:38:08 +000036 ip = numeric_to_ipaddr(arg);
Jan Engelhardt41daaa02008-01-20 13:42:43 +000037 if (ip != NULL)
38 exit_error(PARAMETER_PROBLEM, "iprange match: Bad IP address `%s'\n",
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +000039 arg);
40 range->min_ip = ip->s_addr;
41
Jan Engelhardt41daaa02008-01-20 13:42:43 +000042 if (dash != NULL) {
Jan Engelhardtbd943842008-01-20 13:38:08 +000043 ip = numeric_to_ipaddr(dash+1);
Jan Engelhardt41daaa02008-01-20 13:42:43 +000044 if (ip != NULL)
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +000045 exit_error(PARAMETER_PROBLEM, "iprange match: Bad IP address `%s'\n",
46 dash+1);
47 range->max_ip = ip->s_addr;
Jan Engelhardt41daaa02008-01-20 13:42:43 +000048 } else {
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +000049 range->max_ip = range->min_ip;
Jan Engelhardt41daaa02008-01-20 13:42:43 +000050 }
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +000051}
52
Jan Engelhardt59d16402007-10-04 16:28:39 +000053static int iprange_parse(int c, char **argv, int invert, unsigned int *flags,
54 const void *entry, struct xt_entry_match **match)
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +000055{
56 struct ipt_iprange_info *info = (struct ipt_iprange_info *)(*match)->data;
57
58 switch (c) {
59 case '1':
60 if (*flags & IPRANGE_SRC)
61 exit_error(PARAMETER_PROBLEM,
62 "iprange match: Only use --src-range ONCE!");
63 *flags |= IPRANGE_SRC;
64
65 info->flags |= IPRANGE_SRC;
66 check_inverse(optarg, &invert, &optind, 0);
Jan Engelhardt41daaa02008-01-20 13:42:43 +000067 if (invert)
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +000068 info->flags |= IPRANGE_SRC_INV;
Jan Engelhardt41daaa02008-01-20 13:42:43 +000069 parse_iprange(optarg, &info->src);
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +000070
71 break;
72
73 case '2':
74 if (*flags & IPRANGE_DST)
75 exit_error(PARAMETER_PROBLEM,
76 "iprange match: Only use --dst-range ONCE!");
77 *flags |= IPRANGE_DST;
78
79 info->flags |= IPRANGE_DST;
80 check_inverse(optarg, &invert, &optind, 0);
81 if (invert)
82 info->flags |= IPRANGE_DST_INV;
83
Jan Engelhardt41daaa02008-01-20 13:42:43 +000084 parse_iprange(optarg, &info->dst);
Nicolas Boulianeb9c6ec12004-07-12 07:16:54 +000085
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +000086 break;
87
88 default:
89 return 0;
90 }
91 return 1;
92}
93
Jan Engelhardt41daaa02008-01-20 13:42:43 +000094static void iprange_mt_check(unsigned int flags)
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +000095{
Jan Engelhardt41daaa02008-01-20 13:42:43 +000096 if (flags == 0)
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +000097 exit_error(PARAMETER_PROBLEM,
98 "iprange match: You must specify `--src-range' or `--dst-range'");
99}
100
101static void
102print_iprange(const struct ipt_iprange *range)
103{
104 const unsigned char *byte_min, *byte_max;
105
Jan Engelhardt41daaa02008-01-20 13:42:43 +0000106 byte_min = (const unsigned char *)&range->min_ip;
107 byte_max = (const unsigned char *)&range->max_ip;
108 printf("%u.%u.%u.%u-%u.%u.%u.%u ",
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000109 byte_min[0], byte_min[1], byte_min[2], byte_min[3],
110 byte_max[0], byte_max[1], byte_max[2], byte_max[3]);
111}
112
Jan Engelhardt59d16402007-10-04 16:28:39 +0000113static void iprange_print(const void *ip, const struct xt_entry_match *match,
114 int numeric)
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000115{
Jan Engelhardt41daaa02008-01-20 13:42:43 +0000116 const struct ipt_iprange_info *info = (const void *)match->data;
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000117
118 if (info->flags & IPRANGE_SRC) {
119 printf("source IP range ");
120 if (info->flags & IPRANGE_SRC_INV)
121 printf("! ");
122 print_iprange(&info->src);
123 }
124 if (info->flags & IPRANGE_DST) {
125 printf("destination IP range ");
126 if (info->flags & IPRANGE_DST_INV)
127 printf("! ");
128 print_iprange(&info->dst);
129 }
130}
131
Jan Engelhardt59d16402007-10-04 16:28:39 +0000132static void iprange_save(const void *ip, const struct xt_entry_match *match)
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000133{
Jan Engelhardt41daaa02008-01-20 13:42:43 +0000134 const struct ipt_iprange_info *info = (const void *)match->data;
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000135
136 if (info->flags & IPRANGE_SRC) {
137 if (info->flags & IPRANGE_SRC_INV)
138 printf("! ");
139 printf("--src-range ");
140 print_iprange(&info->src);
141 if (info->flags & IPRANGE_DST)
142 fputc(' ', stdout);
143 }
144 if (info->flags & IPRANGE_DST) {
145 if (info->flags & IPRANGE_DST_INV)
146 printf("! ");
147 printf("--dst-range ");
148 print_iprange(&info->dst);
149 }
150}
151
Jan Engelhardt41daaa02008-01-20 13:42:43 +0000152static struct xtables_match iprange_match = {
153 .version = IPTABLES_VERSION,
154 .name = "iprange",
155 .revision = 0,
156 .family = AF_INET,
157 .size = XT_ALIGN(sizeof(struct ipt_iprange_info)),
158 .userspacesize = XT_ALIGN(sizeof(struct ipt_iprange_info)),
159 .help = iprange_mt_help,
160 .parse = iprange_parse,
161 .final_check = iprange_mt_check,
162 .print = iprange_print,
163 .save = iprange_save,
164 .extra_opts = iprange_mt_opts,
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000165};
166
167void _init(void)
168{
Jan Engelhardt41daaa02008-01-20 13:42:43 +0000169 xtables_register_match(&iprange_match);
Joszef Kadlecsik9cb66152003-04-23 13:27:09 +0000170}