iptables-1.2.9-2.3.1.src.rpm
[iptables.git] / extensions / libipt_iprange.c
1 /* 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. */
12 static void
13 help(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",
20 IPTABLES_VERSION);
21 }
22
23 static struct option opts[] = {
24         { "src-range", 1, 0, '1' },
25         { "dst-range", 1, 0, '2' },
26         {0}
27 };
28
29 /* Initialize the match. */
30 static void
31 init(struct ipt_entry_match *m, unsigned int *nfcache)
32 {
33         /* Can't cache this. */
34         *nfcache |= NFC_UNKNOWN;
35 }
36
37 static void
38 parse_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 */
65 static int
66 parse(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);              
102                 *flags = 1;
103                 break;
104
105         default:
106                 return 0;
107         }
108         return 1;
109 }
110
111 /* Final check; must have specified --src-range or --dst-range. */
112 static void
113 final_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
120 static void
121 print_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. */
133 static void
134 print(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. */
155 static void
156 save(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
176 static
177 struct iptables_match iprange
178 = { NULL,
179     "iprange",
180     IPTABLES_VERSION,
181     IPT_ALIGN(sizeof(struct ipt_iprange_info)),
182     IPT_ALIGN(sizeof(struct ipt_iprange_info)),
183     &help,
184     &init,
185     &parse,
186     &final_check,
187     &print,
188     &save,
189     opts
190 };
191
192 void _init(void)
193 {
194         register_match(&iprange);
195 }