fix for f12, gcc4.4
[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 static void
30 parse_iprange(char *arg, struct ipt_iprange *range)
31 {
32         char *dash;
33         struct in_addr *ip;
34
35         dash = strchr(arg, '-');
36         if (dash)
37                 *dash = '\0';
38                 
39         ip = dotted_to_addr(arg);
40         if (!ip)
41                 exit_error(PARAMETER_PROBLEM, "iprange match: Bad IP address `%s'\n", 
42                            arg);
43         range->min_ip = ip->s_addr;
44
45         if (dash) {
46                 ip = dotted_to_addr(dash+1);
47                 if (!ip)
48                         exit_error(PARAMETER_PROBLEM, "iprange match: Bad IP address `%s'\n",
49                                    dash+1);
50                 range->max_ip = ip->s_addr;
51         } else
52                 range->max_ip = range->min_ip;
53 }
54
55 /* Function which parses command options; returns true if it
56    ate an option */
57 static int
58 parse(int c, char **argv, int invert, unsigned int *flags,
59       const struct ipt_entry *entry,
60       unsigned int *nfcache,
61       struct ipt_entry_match **match)
62 {
63         struct ipt_iprange_info *info = (struct ipt_iprange_info *)(*match)->data;
64
65         switch (c) {
66         case '1':
67                 if (*flags & IPRANGE_SRC)
68                         exit_error(PARAMETER_PROBLEM,
69                                    "iprange match: Only use --src-range ONCE!");
70                 *flags |= IPRANGE_SRC;
71
72                 info->flags |= IPRANGE_SRC;
73                 check_inverse(optarg, &invert, &optind, 0);
74                 if (invert) {
75                         info->flags |= IPRANGE_SRC_INV;
76                 }
77                 parse_iprange(optarg, &info->src);              
78
79                 break;
80
81         case '2':
82                 if (*flags & IPRANGE_DST)
83                         exit_error(PARAMETER_PROBLEM,
84                                    "iprange match: Only use --dst-range ONCE!");
85                 *flags |= IPRANGE_DST;
86
87                 info->flags |= IPRANGE_DST;
88                 check_inverse(optarg, &invert, &optind, 0);
89                 if (invert)
90                         info->flags |= IPRANGE_DST_INV;
91
92                 parse_iprange(optarg, &info->dst);              
93
94                 break;
95
96         default:
97                 return 0;
98         }
99         return 1;
100 }
101
102 /* Final check; must have specified --src-range or --dst-range. */
103 static void
104 final_check(unsigned int flags)
105 {
106         if (!flags)
107                 exit_error(PARAMETER_PROBLEM,
108                            "iprange match: You must specify `--src-range' or `--dst-range'");
109 }
110
111 static void
112 print_iprange(const struct ipt_iprange *range)
113 {
114         const unsigned char *byte_min, *byte_max;
115
116         byte_min = (const unsigned char *) &(range->min_ip);
117         byte_max = (const unsigned char *) &(range->max_ip);
118         printf("%d.%d.%d.%d-%d.%d.%d.%d ", 
119                 byte_min[0], byte_min[1], byte_min[2], byte_min[3],
120                 byte_max[0], byte_max[1], byte_max[2], byte_max[3]);
121 }
122
123 /* Prints out the info. */
124 static void
125 print(const struct ipt_ip *ip,
126       const struct ipt_entry_match *match,
127       int numeric)
128 {
129         struct ipt_iprange_info *info = (struct ipt_iprange_info *)match->data;
130
131         if (info->flags & IPRANGE_SRC) {
132                 printf("source IP range ");
133                 if (info->flags & IPRANGE_SRC_INV)
134                         printf("! ");
135                 print_iprange(&info->src);
136         }
137         if (info->flags & IPRANGE_DST) {
138                 printf("destination IP range ");
139                 if (info->flags & IPRANGE_DST_INV)
140                         printf("! ");
141                 print_iprange(&info->dst);
142         }
143 }
144
145 /* Saves the union ipt_info in parsable form to stdout. */
146 static void
147 save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
148 {
149         struct ipt_iprange_info *info = (struct ipt_iprange_info *)match->data;
150
151         if (info->flags & IPRANGE_SRC) {
152                 if (info->flags & IPRANGE_SRC_INV)
153                         printf("! ");
154                 printf("--src-range ");
155                 print_iprange(&info->src);
156                 if (info->flags & IPRANGE_DST)
157                         fputc(' ', stdout);
158         }
159         if (info->flags & IPRANGE_DST) {
160                 if (info->flags & IPRANGE_DST_INV)
161                         printf("! ");
162                 printf("--dst-range ");
163                 print_iprange(&info->dst);
164         }
165 }
166
167 static struct iptables_match iprange = { 
168         .next           = NULL,
169         .name           = "iprange",
170         .version        = IPTABLES_VERSION,
171         .size           = IPT_ALIGN(sizeof(struct ipt_iprange_info)),
172         .userspacesize  = IPT_ALIGN(sizeof(struct ipt_iprange_info)),
173         .help           = &help,
174         .parse          = &parse,
175         .final_check    = &final_check,
176         .print          = &print,
177         .save           = &save,
178         .extra_opts     = opts
179 };
180
181 void _init(void)
182 {
183         register_match(&iprange);
184 }