]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - net/netfilter/ipset/ip_set_hash_ipport.c
i2o: convert bus code to use dev_groups
[karo-tx-linux.git] / net / netfilter / ipset / ip_set_hash_ipport.c
1 /* Copyright (C) 2003-2013 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 version 2 as
5  * published by the Free Software Foundation.
6  */
7
8 /* Kernel module implementing an IP set type: the hash:ip,port type */
9
10 #include <linux/jhash.h>
11 #include <linux/module.h>
12 #include <linux/ip.h>
13 #include <linux/skbuff.h>
14 #include <linux/errno.h>
15 #include <linux/random.h>
16 #include <net/ip.h>
17 #include <net/ipv6.h>
18 #include <net/netlink.h>
19 #include <net/tcp.h>
20
21 #include <linux/netfilter.h>
22 #include <linux/netfilter/ipset/pfxlen.h>
23 #include <linux/netfilter/ipset/ip_set.h>
24 #include <linux/netfilter/ipset/ip_set_getport.h>
25 #include <linux/netfilter/ipset/ip_set_hash.h>
26
27 #define REVISION_MIN    0
28 /*                      1    SCTP and UDPLITE support added */
29 #define REVISION_MAX    2 /* Counters support added */
30
31 MODULE_LICENSE("GPL");
32 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
33 IP_SET_MODULE_DESC("hash:ip,port", REVISION_MIN, REVISION_MAX);
34 MODULE_ALIAS("ip_set_hash:ip,port");
35
36 /* Type specific function prefix */
37 #define HTYPE           hash_ipport
38
39 /* IPv4 variants */
40
41 /* Member elements */
42 struct hash_ipport4_elem {
43         __be32 ip;
44         __be16 port;
45         u8 proto;
46         u8 padding;
47 };
48
49 struct hash_ipport4t_elem {
50         __be32 ip;
51         __be16 port;
52         u8 proto;
53         u8 padding;
54         unsigned long timeout;
55 };
56
57 struct hash_ipport4c_elem {
58         __be32 ip;
59         __be16 port;
60         u8 proto;
61         u8 padding;
62         struct ip_set_counter counter;
63 };
64
65 struct hash_ipport4ct_elem {
66         __be32 ip;
67         __be16 port;
68         u8 proto;
69         u8 padding;
70         struct ip_set_counter counter;
71         unsigned long timeout;
72 };
73
74 /* Common functions */
75
76 static inline bool
77 hash_ipport4_data_equal(const struct hash_ipport4_elem *ip1,
78                         const struct hash_ipport4_elem *ip2,
79                         u32 *multi)
80 {
81         return ip1->ip == ip2->ip &&
82                ip1->port == ip2->port &&
83                ip1->proto == ip2->proto;
84 }
85
86 static bool
87 hash_ipport4_data_list(struct sk_buff *skb,
88                        const struct hash_ipport4_elem *data)
89 {
90         if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, data->ip) ||
91             nla_put_net16(skb, IPSET_ATTR_PORT, data->port) ||
92             nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto))
93                 goto nla_put_failure;
94         return 0;
95
96 nla_put_failure:
97         return 1;
98 }
99
100 static inline void
101 hash_ipport4_data_next(struct hash_ipport4_elem *next,
102                        const struct hash_ipport4_elem *d)
103 {
104         next->ip = d->ip;
105         next->port = d->port;
106 }
107
108 #define MTYPE           hash_ipport4
109 #define PF              4
110 #define HOST_MASK       32
111 #define HKEY_DATALEN    sizeof(struct hash_ipport4_elem)
112 #include "ip_set_hash_gen.h"
113
114 static int
115 hash_ipport4_kadt(struct ip_set *set, const struct sk_buff *skb,
116                   const struct xt_action_param *par,
117                   enum ipset_adt adt, struct ip_set_adt_opt *opt)
118 {
119         const struct hash_ipport *h = set->data;
120         ipset_adtfn adtfn = set->variant->adt[adt];
121         struct hash_ipport4_elem e = { };
122         struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h);
123
124         if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
125                                  &e.port, &e.proto))
126                 return -EINVAL;
127
128         ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip);
129         return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
130 }
131
132 static int
133 hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
134                   enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
135 {
136         const struct hash_ipport *h = set->data;
137         ipset_adtfn adtfn = set->variant->adt[adt];
138         struct hash_ipport4_elem e = { };
139         struct ip_set_ext ext = IP_SET_INIT_UEXT(h);
140         u32 ip, ip_to, p = 0, port, port_to;
141         bool with_ports = false;
142         int ret;
143
144         if (unlikely(!tb[IPSET_ATTR_IP] ||
145                      !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
146                      !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
147                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
148                      !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
149                      !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES)))
150                 return -IPSET_ERR_PROTOCOL;
151
152         if (tb[IPSET_ATTR_LINENO])
153                 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
154
155         ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &e.ip) ||
156               ip_set_get_extensions(set, tb, &ext);
157         if (ret)
158                 return ret;
159
160         if (tb[IPSET_ATTR_PORT])
161                 e.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
162         else
163                 return -IPSET_ERR_PROTOCOL;
164
165         if (tb[IPSET_ATTR_PROTO]) {
166                 e.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
167                 with_ports = ip_set_proto_with_ports(e.proto);
168
169                 if (e.proto == 0)
170                         return -IPSET_ERR_INVALID_PROTO;
171         } else
172                 return -IPSET_ERR_MISSING_PROTO;
173
174         if (!(with_ports || e.proto == IPPROTO_ICMP))
175                 e.port = 0;
176
177         if (adt == IPSET_TEST ||
178             !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
179               tb[IPSET_ATTR_PORT_TO])) {
180                 ret = adtfn(set, &e, &ext, &ext, flags);
181                 return ip_set_eexist(ret, flags) ? 0 : ret;
182         }
183
184         ip_to = ip = ntohl(e.ip);
185         if (tb[IPSET_ATTR_IP_TO]) {
186                 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
187                 if (ret)
188                         return ret;
189                 if (ip > ip_to)
190                         swap(ip, ip_to);
191         } else if (tb[IPSET_ATTR_CIDR]) {
192                 u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
193
194                 if (!cidr || cidr > 32)
195                         return -IPSET_ERR_INVALID_CIDR;
196                 ip_set_mask_from_to(ip, ip_to, cidr);
197         }
198
199         port_to = port = ntohs(e.port);
200         if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
201                 port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
202                 if (port > port_to)
203                         swap(port, port_to);
204         }
205
206         if (retried)
207                 ip = ntohl(h->next.ip);
208         for (; !before(ip_to, ip); ip++) {
209                 p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
210                                                        : port;
211                 for (; p <= port_to; p++) {
212                         e.ip = htonl(ip);
213                         e.port = htons(p);
214                         ret = adtfn(set, &e, &ext, &ext, flags);
215
216                         if (ret && !ip_set_eexist(ret, flags))
217                                 return ret;
218                         else
219                                 ret = 0;
220                 }
221         }
222         return ret;
223 }
224
225 /* IPv6 variants */
226
227 struct hash_ipport6_elem {
228         union nf_inet_addr ip;
229         __be16 port;
230         u8 proto;
231         u8 padding;
232 };
233
234 struct hash_ipport6t_elem {
235         union nf_inet_addr ip;
236         __be16 port;
237         u8 proto;
238         u8 padding;
239         unsigned long timeout;
240 };
241
242 struct hash_ipport6c_elem {
243         union nf_inet_addr ip;
244         __be16 port;
245         u8 proto;
246         u8 padding;
247         struct ip_set_counter counter;
248 };
249
250 struct hash_ipport6ct_elem {
251         union nf_inet_addr ip;
252         __be16 port;
253         u8 proto;
254         u8 padding;
255         struct ip_set_counter counter;
256         unsigned long timeout;
257 };
258
259 /* Common functions */
260
261 static inline bool
262 hash_ipport6_data_equal(const struct hash_ipport6_elem *ip1,
263                         const struct hash_ipport6_elem *ip2,
264                         u32 *multi)
265 {
266         return ipv6_addr_equal(&ip1->ip.in6, &ip2->ip.in6) &&
267                ip1->port == ip2->port &&
268                ip1->proto == ip2->proto;
269 }
270
271 static bool
272 hash_ipport6_data_list(struct sk_buff *skb,
273                        const struct hash_ipport6_elem *data)
274 {
275         if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip.in6) ||
276             nla_put_net16(skb, IPSET_ATTR_PORT, data->port) ||
277             nla_put_u8(skb, IPSET_ATTR_PROTO, data->proto))
278                 goto nla_put_failure;
279         return 0;
280
281 nla_put_failure:
282         return 1;
283 }
284
285 static inline void
286 hash_ipport6_data_next(struct hash_ipport4_elem *next,
287                        const struct hash_ipport6_elem *d)
288 {
289         next->port = d->port;
290 }
291
292 #undef MTYPE
293 #undef PF
294 #undef HOST_MASK
295 #undef HKEY_DATALEN
296
297 #define MTYPE           hash_ipport6
298 #define PF              6
299 #define HOST_MASK       128
300 #define HKEY_DATALEN    sizeof(struct hash_ipport6_elem)
301 #define IP_SET_EMIT_CREATE
302 #include "ip_set_hash_gen.h"
303
304 static int
305 hash_ipport6_kadt(struct ip_set *set, const struct sk_buff *skb,
306                   const struct xt_action_param *par,
307                   enum ipset_adt adt, struct ip_set_adt_opt *opt)
308 {
309         const struct hash_ipport *h = set->data;
310         ipset_adtfn adtfn = set->variant->adt[adt];
311         struct hash_ipport6_elem e = { };
312         struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, h);
313
314         if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
315                                  &e.port, &e.proto))
316                 return -EINVAL;
317
318         ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6);
319         return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
320 }
321
322 static int
323 hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
324                   enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
325 {
326         const struct hash_ipport *h = set->data;
327         ipset_adtfn adtfn = set->variant->adt[adt];
328         struct hash_ipport6_elem e = { };
329         struct ip_set_ext ext = IP_SET_INIT_UEXT(h);
330         u32 port, port_to;
331         bool with_ports = false;
332         int ret;
333
334         if (unlikely(!tb[IPSET_ATTR_IP] ||
335                      !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) ||
336                      !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
337                      !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
338                      !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
339                      !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
340                      tb[IPSET_ATTR_IP_TO] ||
341                      tb[IPSET_ATTR_CIDR]))
342                 return -IPSET_ERR_PROTOCOL;
343
344         if (tb[IPSET_ATTR_LINENO])
345                 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
346
347         ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip) ||
348               ip_set_get_extensions(set, tb, &ext);
349         if (ret)
350                 return ret;
351
352         if (tb[IPSET_ATTR_PORT])
353                 e.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
354         else
355                 return -IPSET_ERR_PROTOCOL;
356
357         if (tb[IPSET_ATTR_PROTO]) {
358                 e.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]);
359                 with_ports = ip_set_proto_with_ports(e.proto);
360
361                 if (e.proto == 0)
362                         return -IPSET_ERR_INVALID_PROTO;
363         } else
364                 return -IPSET_ERR_MISSING_PROTO;
365
366         if (!(with_ports || e.proto == IPPROTO_ICMPV6))
367                 e.port = 0;
368
369         if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) {
370                 ret = adtfn(set, &e, &ext, &ext, flags);
371                 return ip_set_eexist(ret, flags) ? 0 : ret;
372         }
373
374         port = ntohs(e.port);
375         port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
376         if (port > port_to)
377                 swap(port, port_to);
378
379         if (retried)
380                 port = ntohs(h->next.port);
381         for (; port <= port_to; port++) {
382                 e.port = htons(port);
383                 ret = adtfn(set, &e, &ext, &ext, flags);
384
385                 if (ret && !ip_set_eexist(ret, flags))
386                         return ret;
387                 else
388                         ret = 0;
389         }
390         return ret;
391 }
392
393 static struct ip_set_type hash_ipport_type __read_mostly = {
394         .name           = "hash:ip,port",
395         .protocol       = IPSET_PROTOCOL,
396         .features       = IPSET_TYPE_IP | IPSET_TYPE_PORT,
397         .dimension      = IPSET_DIM_TWO,
398         .family         = NFPROTO_UNSPEC,
399         .revision_min   = REVISION_MIN,
400         .revision_max   = REVISION_MAX,
401         .create         = hash_ipport_create,
402         .create_policy  = {
403                 [IPSET_ATTR_HASHSIZE]   = { .type = NLA_U32 },
404                 [IPSET_ATTR_MAXELEM]    = { .type = NLA_U32 },
405                 [IPSET_ATTR_PROBES]     = { .type = NLA_U8 },
406                 [IPSET_ATTR_RESIZE]     = { .type = NLA_U8  },
407                 [IPSET_ATTR_PROTO]      = { .type = NLA_U8 },
408                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
409                 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
410         },
411         .adt_policy     = {
412                 [IPSET_ATTR_IP]         = { .type = NLA_NESTED },
413                 [IPSET_ATTR_IP_TO]      = { .type = NLA_NESTED },
414                 [IPSET_ATTR_PORT]       = { .type = NLA_U16 },
415                 [IPSET_ATTR_PORT_TO]    = { .type = NLA_U16 },
416                 [IPSET_ATTR_CIDR]       = { .type = NLA_U8 },
417                 [IPSET_ATTR_PROTO]      = { .type = NLA_U8 },
418                 [IPSET_ATTR_TIMEOUT]    = { .type = NLA_U32 },
419                 [IPSET_ATTR_LINENO]     = { .type = NLA_U32 },
420                 [IPSET_ATTR_BYTES]      = { .type = NLA_U64 },
421                 [IPSET_ATTR_PACKETS]    = { .type = NLA_U64 },
422         },
423         .me             = THIS_MODULE,
424 };
425
426 static int __init
427 hash_ipport_init(void)
428 {
429         return ip_set_type_register(&hash_ipport_type);
430 }
431
432 static void __exit
433 hash_ipport_fini(void)
434 {
435         ip_set_type_unregister(&hash_ipport_type);
436 }
437
438 module_init(hash_ipport_init);
439 module_exit(hash_ipport_fini);