1d4f8074caaeae33e86114049447d9c0e07e461b
[iptables.git] / ipset / ipset_portmap.c
1 /* Copyright 2004 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
2  *
3  * This program is free software; you can redistribute it and/or modify   
4  * it under the terms of the GNU General Public License as published by   
5  * the Free Software Foundation; either version 2 of the License, or      
6  * (at your option) any later version.                                    
7  *                                                                         
8  * This program is distributed in the hope that it will be useful,        
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of         
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          
11  * GNU General Public License for more details.                           
12  *                                                                         
13  * You should have received a copy of the GNU General Public License      
14  * along with this program; if not, write to the Free Software            
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  */
17
18
19 #include <stdio.h>
20 #include <string.h>
21 #include <sys/socket.h>
22 #include <netinet/in.h>
23 #include <arpa/inet.h>
24
25 #include <linux/netfilter_ipv4/ip_set_portmap.h>
26 #include "ipset.h"
27
28
29 #define BUFLEN 30;
30
31 #define OPT_CREATE_FROM    0x01U
32 #define OPT_CREATE_TO      0x02U
33
34 #define OPT_ADDDEL_PORT      0x01U
35
36 /* Initialize the create. */
37 void create_init(void *data)
38 {
39         DP("create INIT");
40         /* Nothing */
41 }
42
43 /* Function which parses command options; returns true if it ate an option */
44 int create_parse(int c, char *argv[], void *data, unsigned *flags)
45 {
46         struct ip_set_req_portmap_create *mydata =
47             (struct ip_set_req_portmap_create *) data;
48
49         DP("create_parse");
50
51         switch (c) {
52         case '1':
53                 parse_port(optarg, &mydata->from);
54
55                 *flags |= OPT_CREATE_FROM;
56
57                 DP("--from %x (%s)", mydata->from,
58                    port_tostring(mydata->from, 0));
59
60                 break;
61
62         case '2':
63                 parse_port(optarg, &mydata->to);
64
65                 *flags |= OPT_CREATE_TO;
66
67                 DP("--to %x (%s)", mydata->to,
68                    port_tostring(mydata->to, 0));
69
70                 break;
71
72         default:
73                 return 0;
74         }
75
76         return 1;
77 }
78
79 /* Final check; exit if not ok. */
80 void create_final(void *data, unsigned int flags)
81 {
82         struct ip_set_req_portmap_create *mydata =
83             (struct ip_set_req_portmap_create *) data;
84
85         if (flags == 0) {
86                 exit_error(PARAMETER_PROBLEM,
87                            "Need to specify --from and --to\n");
88         } else {
89                 /* --from --to */
90                 if ((flags & OPT_CREATE_FROM) == 0
91                     || (flags & OPT_CREATE_TO) == 0)
92                         exit_error(PARAMETER_PROBLEM,
93                                    "Need to specify both --from and --to\n");
94         }
95
96         DP("from : %x to: %x  diff: %d", mydata->from, mydata->to,
97            mydata->to - mydata->from);
98
99         if (mydata->from > mydata->to)
100                 exit_error(PARAMETER_PROBLEM,
101                            "From can't be lower than to.\n");
102
103         if (mydata->to - mydata->from > MAX_RANGE)
104                 exit_error(PARAMETER_PROBLEM,
105                            "Range too large. Max is %d ports in range\n",
106                            MAX_RANGE+1);
107 }
108
109 /* Create commandline options */
110 static struct option create_opts[] = {
111         {"from", 1, 0, '1'},
112         {"to", 1, 0, '2'},
113         {0}
114 };
115
116 /* Add, del, test parser */
117 ip_set_ip_t adt_parser(unsigned cmd, const char *optarg, void *data)
118 {
119         struct ip_set_req_portmap *mydata =
120             (struct ip_set_req_portmap *) data;
121
122         parse_port(optarg, &mydata->port);
123         DP("%s", port_tostring(mydata->port, 0));
124
125         return 1;       
126 }
127
128 /*
129  * Print and save
130  */
131
132 void initheader(struct set *set, const void *data)
133 {
134         struct ip_set_req_portmap_create *header =
135             (struct ip_set_req_portmap_create *) data;
136         struct ip_set_portmap *map =
137                 (struct ip_set_portmap *) set->settype->header;
138
139         memset(map, 0, sizeof(struct ip_set_portmap));
140         map->first_port = header->from;
141         map->last_port = header->to;
142 }
143
144 void printheader(struct set *set, unsigned options)
145 {
146         struct ip_set_portmap *mysetdata =
147             (struct ip_set_portmap *) set->settype->header;
148
149         printf(" from: %s", port_tostring(mysetdata->first_port, options));
150         printf(" to: %s\n", port_tostring(mysetdata->last_port, options));
151 }
152
153 void printports_sorted(struct set *set, void *data, size_t len, unsigned options)
154 {
155         struct ip_set_portmap *mysetdata =
156             (struct ip_set_portmap *) set->settype->header;
157         u_int32_t addr = mysetdata->first_port;
158
159         DP("%u -- %u", mysetdata->first_port, mysetdata->last_port);
160         while (addr <= mysetdata->last_port) {
161                 if (test_bit(addr - mysetdata->first_port, data))
162                         printf("%s\n", port_tostring(addr, options));
163                 addr++;
164         }
165 }
166
167 char * binding_port_tostring(struct set *set, ip_set_ip_t ip, unsigned options)
168 {
169         return port_tostring(ip, options);
170 }
171
172 void saveheader(struct set *set, unsigned options)
173 {
174         struct ip_set_portmap *mysetdata =
175             (struct ip_set_portmap *) set->settype->header;
176
177         printf("-N %s %s --from %s", 
178                set->name,
179                set->settype->typename,
180                port_tostring(mysetdata->first_port, options));
181         printf(" --to %s\n", 
182                port_tostring(mysetdata->last_port, options));
183 }
184
185 void saveports(struct set *set, void *data, size_t len, unsigned options)
186 {
187         struct ip_set_portmap *mysetdata =
188             (struct ip_set_portmap *) set->settype->header;
189         u_int32_t addr = mysetdata->first_port;
190
191         while (addr <= mysetdata->last_port) {
192                 if (test_bit(addr - mysetdata->first_port, data))
193                         printf("-A %s %s\n",
194                                set->name,
195                                port_tostring(addr, options));
196                 addr++;
197         }
198 }
199
200 void usage(void)
201 {
202         printf
203             ("-N set portmap --from PORT --to PORT\n"
204              "-A set PORT\n"
205              "-D set PORT\n"
206              "-T set PORT\n");
207 }
208
209 static struct settype settype_portmap = {
210         .typename = SETTYPE_NAME,
211         .protocol_version = IP_SET_PROTOCOL_VERSION,
212
213         /* Create */
214         .create_size = sizeof(struct ip_set_req_portmap_create),
215         .create_init = &create_init,
216         .create_parse = &create_parse,
217         .create_final = &create_final,
218         .create_opts = create_opts,
219
220         /* Add/del/test */
221         .adt_size = sizeof(struct ip_set_req_portmap),
222         .adt_parser = &adt_parser,
223
224         /* Printing */
225         .header_size = sizeof(struct ip_set_portmap),
226         .initheader = &initheader,
227         .printheader = &printheader,
228         .printips = &printports_sorted, /* We only have sorted version */
229         .printips_sorted = &printports_sorted,
230         .saveheader = &saveheader,
231         .saveips = &saveports,
232         
233         /* Bindings */
234         .bindip_tostring = &binding_port_tostring,
235         .bindip_parse = &parse_port,
236
237         .usage = &usage,
238 };
239
240 void _init(void)
241 {
242         settype_register(&settype_portmap);
243
244 }