iptables-1.3.2-20050720
[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                         printf("hoho\n");
77                 }
78                 parse_iprange(optarg, &info->src);              
79
80                 break;
81
82         case '2':
83                 if (*flags & IPRANGE_DST)
84                         exit_error(PARAMETER_PROBLEM,
85                                    "iprange match: Only use --dst-range ONCE!");
86                 *flags |= IPRANGE_DST;
87
88                 info->flags |= IPRANGE_DST;
89                 check_inverse(optarg, &invert, &optind, 0);
90                 if (invert)
91                         info->flags |= IPRANGE_DST_INV;
92
93                 parse_iprange(optarg, &info->dst);              
94
95                 break;
96
97         default:
98                 return 0;
99         }
100         return 1;
101 }
102
103 /* Final check; must have specified --src-range or --dst-range. */
104 static void
105 final_check(unsigned int flags)
106 {
107         if (!flags)
108                 exit_error(PARAMETER_PROBLEM,
109                            "iprange match: You must specify `--src-range' or `--dst-range'");
110 }
111
112 static void
113 print_iprange(const struct ipt_iprange *range)
114 {
115         const unsigned char *byte_min, *byte_max;
116
117         byte_min = (const unsigned char *) &(range->min_ip);
118         byte_max = (const unsigned char *) &(range->max_ip);
119         printf("%d.%d.%d.%d-%d.%d.%d.%d ", 
120                 byte_min[0], byte_min[1], byte_min[2], byte_min[3],
121                 byte_max[0], byte_max[1], byte_max[2], byte_max[3]);
122 }
123
124 /* Prints out the info. */
125 static void
126 print(const struct ipt_ip *ip,
127       const struct ipt_entry_match *match,
128       int numeric)
129 {
130         struct ipt_iprange_info *info = (struct ipt_iprange_info *)match->data;
131
132         if (info->flags & IPRANGE_SRC) {
133                 printf("source IP range ");
134                 if (info->flags & IPRANGE_SRC_INV)
135                         printf("! ");
136                 print_iprange(&info->src);
137         }
138         if (info->flags & IPRANGE_DST) {
139                 printf("destination IP range ");
140                 if (info->flags & IPRANGE_DST_INV)
141                         printf("! ");
142                 print_iprange(&info->dst);
143         }
144 }
145
146 /* Saves the union ipt_info in parsable form to stdout. */
147 static void
148 save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
149 {
150         struct ipt_iprange_info *info = (struct ipt_iprange_info *)match->data;
151
152         if (info->flags & IPRANGE_SRC) {
153                 if (info->flags & IPRANGE_SRC_INV)
154                         printf("! ");
155                 printf("--src-range ");
156                 print_iprange(&info->src);
157                 if (info->flags & IPRANGE_DST)
158                         fputc(' ', stdout);
159         }
160         if (info->flags & IPRANGE_DST) {
161                 if (info->flags & IPRANGE_DST_INV)
162                         printf("! ");
163                 printf("--dst-range ");
164                 print_iprange(&info->dst);
165         }
166 }
167
168 static struct iptables_match iprange = { 
169         .next           = NULL,
170         .name           = "iprange",
171         .version        = IPTABLES_VERSION,
172         .size           = IPT_ALIGN(sizeof(struct ipt_iprange_info)),
173         .userspacesize  = IPT_ALIGN(sizeof(struct ipt_iprange_info)),
174         .help           = &help,
175         .parse          = &parse,
176         .final_check    = &final_check,
177         .print          = &print,
178         .save           = &save,
179         .extra_opts     = opts
180 };
181
182 void _init(void)
183 {
184         register_match(&iprange);
185 }