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