1 /* Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
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.
8 /* Kernel module implementing an IP set type: the bitmap:port type */
10 #include <linux/module.h>
12 #include <linux/skbuff.h>
13 #include <linux/errno.h>
14 #include <linux/netlink.h>
15 #include <linux/jiffies.h>
16 #include <linux/timer.h>
17 #include <net/netlink.h>
19 #include <linux/netfilter/ipset/ip_set.h>
20 #include <linux/netfilter/ipset/ip_set_bitmap.h>
21 #include <linux/netfilter/ipset/ip_set_getport.h>
23 #define IPSET_TYPE_REV_MIN 0
24 /* 1 Counter support added */
25 /* 2 Comment support added */
26 #define IPSET_TYPE_REV_MAX 3 /* skbinfo support added */
28 MODULE_LICENSE("GPL");
29 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
30 IP_SET_MODULE_DESC("bitmap:port", IPSET_TYPE_REV_MIN
, IPSET_TYPE_REV_MAX
);
31 MODULE_ALIAS("ip_set_bitmap:port");
33 #define MTYPE bitmap_port
37 void *members
; /* the set members */
38 u16 first_port
; /* host byte order, included in range */
39 u16 last_port
; /* host byte order, included in range */
40 u32 elements
; /* number of max elements in the set */
41 size_t memsize
; /* members size */
42 struct timer_list gc
; /* garbage collection */
43 unsigned char extensions
[0] /* data extensions */
44 __aligned(__alignof__(u64
));
47 /* ADT structure for generic function args */
48 struct bitmap_port_adt_elem
{
53 port_to_id(const struct bitmap_port
*m
, u16 port
)
55 return port
- m
->first_port
;
58 /* Common functions */
61 bitmap_port_do_test(const struct bitmap_port_adt_elem
*e
,
62 const struct bitmap_port
*map
, size_t dsize
)
64 return !!test_bit(e
->id
, map
->members
);
68 bitmap_port_gc_test(u16 id
, const struct bitmap_port
*map
, size_t dsize
)
70 return !!test_bit(id
, map
->members
);
74 bitmap_port_do_add(const struct bitmap_port_adt_elem
*e
,
75 struct bitmap_port
*map
, u32 flags
, size_t dsize
)
77 return !!test_bit(e
->id
, map
->members
);
81 bitmap_port_do_del(const struct bitmap_port_adt_elem
*e
,
82 struct bitmap_port
*map
)
84 return !test_and_clear_bit(e
->id
, map
->members
);
88 bitmap_port_do_list(struct sk_buff
*skb
, const struct bitmap_port
*map
, u32 id
,
91 return nla_put_net16(skb
, IPSET_ATTR_PORT
,
92 htons(map
->first_port
+ id
));
96 bitmap_port_do_head(struct sk_buff
*skb
, const struct bitmap_port
*map
)
98 return nla_put_net16(skb
, IPSET_ATTR_PORT
, htons(map
->first_port
)) ||
99 nla_put_net16(skb
, IPSET_ATTR_PORT_TO
, htons(map
->last_port
));
103 bitmap_port_kadt(struct ip_set
*set
, const struct sk_buff
*skb
,
104 const struct xt_action_param
*par
,
105 enum ipset_adt adt
, struct ip_set_adt_opt
*opt
)
107 struct bitmap_port
*map
= set
->data
;
108 ipset_adtfn adtfn
= set
->variant
->adt
[adt
];
109 struct bitmap_port_adt_elem e
= { .id
= 0 };
110 struct ip_set_ext ext
= IP_SET_INIT_KEXT(skb
, opt
, set
);
114 if (!ip_set_get_ip_port(skb
, opt
->family
,
115 opt
->flags
& IPSET_DIM_ONE_SRC
, &__port
))
118 port
= ntohs(__port
);
120 if (port
< map
->first_port
|| port
> map
->last_port
)
121 return -IPSET_ERR_BITMAP_RANGE
;
123 e
.id
= port_to_id(map
, port
);
125 return adtfn(set
, &e
, &ext
, &opt
->ext
, opt
->cmdflags
);
129 bitmap_port_uadt(struct ip_set
*set
, struct nlattr
*tb
[],
130 enum ipset_adt adt
, u32
*lineno
, u32 flags
, bool retried
)
132 struct bitmap_port
*map
= set
->data
;
133 ipset_adtfn adtfn
= set
->variant
->adt
[adt
];
134 struct bitmap_port_adt_elem e
= { .id
= 0 };
135 struct ip_set_ext ext
= IP_SET_INIT_UEXT(set
);
136 u32 port
; /* wraparound */
140 if (tb
[IPSET_ATTR_LINENO
])
141 *lineno
= nla_get_u32(tb
[IPSET_ATTR_LINENO
]);
143 if (unlikely(!ip_set_attr_netorder(tb
, IPSET_ATTR_PORT
) ||
144 !ip_set_optattr_netorder(tb
, IPSET_ATTR_PORT_TO
)))
145 return -IPSET_ERR_PROTOCOL
;
147 port
= ip_set_get_h16(tb
[IPSET_ATTR_PORT
]);
148 if (port
< map
->first_port
|| port
> map
->last_port
)
149 return -IPSET_ERR_BITMAP_RANGE
;
150 ret
= ip_set_get_extensions(set
, tb
, &ext
);
154 if (adt
== IPSET_TEST
) {
155 e
.id
= port_to_id(map
, port
);
156 return adtfn(set
, &e
, &ext
, &ext
, flags
);
159 if (tb
[IPSET_ATTR_PORT_TO
]) {
160 port_to
= ip_set_get_h16(tb
[IPSET_ATTR_PORT_TO
]);
161 if (port
> port_to
) {
163 if (port
< map
->first_port
)
164 return -IPSET_ERR_BITMAP_RANGE
;
170 if (port_to
> map
->last_port
)
171 return -IPSET_ERR_BITMAP_RANGE
;
173 for (; port
<= port_to
; port
++) {
174 e
.id
= port_to_id(map
, port
);
175 ret
= adtfn(set
, &e
, &ext
, &ext
, flags
);
177 if (ret
&& !ip_set_eexist(ret
, flags
))
186 bitmap_port_same_set(const struct ip_set
*a
, const struct ip_set
*b
)
188 const struct bitmap_port
*x
= a
->data
;
189 const struct bitmap_port
*y
= b
->data
;
191 return x
->first_port
== y
->first_port
&&
192 x
->last_port
== y
->last_port
&&
193 a
->timeout
== b
->timeout
&&
194 a
->extensions
== b
->extensions
;
199 struct bitmap_port_elem
{
202 #include "ip_set_bitmap_gen.h"
204 /* Create bitmap:ip type of sets */
207 init_map_port(struct ip_set
*set
, struct bitmap_port
*map
,
208 u16 first_port
, u16 last_port
)
210 map
->members
= ip_set_alloc(map
->memsize
);
213 map
->first_port
= first_port
;
214 map
->last_port
= last_port
;
215 set
->timeout
= IPSET_NO_TIMEOUT
;
218 set
->family
= NFPROTO_UNSPEC
;
224 bitmap_port_create(struct net
*net
, struct ip_set
*set
, struct nlattr
*tb
[],
227 struct bitmap_port
*map
;
228 u16 first_port
, last_port
;
231 if (unlikely(!ip_set_attr_netorder(tb
, IPSET_ATTR_PORT
) ||
232 !ip_set_attr_netorder(tb
, IPSET_ATTR_PORT_TO
) ||
233 !ip_set_optattr_netorder(tb
, IPSET_ATTR_TIMEOUT
) ||
234 !ip_set_optattr_netorder(tb
, IPSET_ATTR_CADT_FLAGS
)))
235 return -IPSET_ERR_PROTOCOL
;
237 first_port
= ip_set_get_h16(tb
[IPSET_ATTR_PORT
]);
238 last_port
= ip_set_get_h16(tb
[IPSET_ATTR_PORT_TO
]);
239 if (first_port
> last_port
) {
240 u16 tmp
= first_port
;
242 first_port
= last_port
;
246 elements
= last_port
- first_port
+ 1;
247 set
->dsize
= ip_set_elem_len(set
, tb
, 0, 0);
248 map
= ip_set_alloc(sizeof(*map
) + elements
* set
->dsize
);
252 map
->elements
= elements
;
253 map
->memsize
= bitmap_bytes(0, map
->elements
);
254 set
->variant
= &bitmap_port
;
255 if (!init_map_port(set
, map
, first_port
, last_port
)) {
259 if (tb
[IPSET_ATTR_TIMEOUT
]) {
260 set
->timeout
= ip_set_timeout_uget(tb
[IPSET_ATTR_TIMEOUT
]);
261 bitmap_port_gc_init(set
, bitmap_port_gc
);
266 static struct ip_set_type bitmap_port_type
= {
267 .name
= "bitmap:port",
268 .protocol
= IPSET_PROTOCOL
,
269 .features
= IPSET_TYPE_PORT
,
270 .dimension
= IPSET_DIM_ONE
,
271 .family
= NFPROTO_UNSPEC
,
272 .revision_min
= IPSET_TYPE_REV_MIN
,
273 .revision_max
= IPSET_TYPE_REV_MAX
,
274 .create
= bitmap_port_create
,
276 [IPSET_ATTR_PORT
] = { .type
= NLA_U16
},
277 [IPSET_ATTR_PORT_TO
] = { .type
= NLA_U16
},
278 [IPSET_ATTR_TIMEOUT
] = { .type
= NLA_U32
},
279 [IPSET_ATTR_CADT_FLAGS
] = { .type
= NLA_U32
},
282 [IPSET_ATTR_PORT
] = { .type
= NLA_U16
},
283 [IPSET_ATTR_PORT_TO
] = { .type
= NLA_U16
},
284 [IPSET_ATTR_TIMEOUT
] = { .type
= NLA_U32
},
285 [IPSET_ATTR_LINENO
] = { .type
= NLA_U32
},
286 [IPSET_ATTR_BYTES
] = { .type
= NLA_U64
},
287 [IPSET_ATTR_PACKETS
] = { .type
= NLA_U64
},
288 [IPSET_ATTR_COMMENT
] = { .type
= NLA_NUL_STRING
,
289 .len
= IPSET_MAX_COMMENT_SIZE
},
290 [IPSET_ATTR_SKBMARK
] = { .type
= NLA_U64
},
291 [IPSET_ATTR_SKBPRIO
] = { .type
= NLA_U32
},
292 [IPSET_ATTR_SKBQUEUE
] = { .type
= NLA_U16
},
298 bitmap_port_init(void)
300 return ip_set_type_register(&bitmap_port_type
);
304 bitmap_port_fini(void)
307 ip_set_type_unregister(&bitmap_port_type
);
310 module_init(bitmap_port_init
);
311 module_exit(bitmap_port_fini
);