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 struct ip_set
*set
; /* attached to this ip_set */
44 unsigned char extensions
[0] /* data extensions */
45 __aligned(__alignof__(u64
));
48 /* ADT structure for generic function args */
49 struct bitmap_port_adt_elem
{
54 port_to_id(const struct bitmap_port
*m
, u16 port
)
56 return port
- m
->first_port
;
59 /* Common functions */
62 bitmap_port_do_test(const struct bitmap_port_adt_elem
*e
,
63 const struct bitmap_port
*map
, size_t dsize
)
65 return !!test_bit(e
->id
, map
->members
);
69 bitmap_port_gc_test(u16 id
, const struct bitmap_port
*map
, size_t dsize
)
71 return !!test_bit(id
, map
->members
);
75 bitmap_port_do_add(const struct bitmap_port_adt_elem
*e
,
76 struct bitmap_port
*map
, u32 flags
, size_t dsize
)
78 return !!test_bit(e
->id
, map
->members
);
82 bitmap_port_do_del(const struct bitmap_port_adt_elem
*e
,
83 struct bitmap_port
*map
)
85 return !test_and_clear_bit(e
->id
, map
->members
);
89 bitmap_port_do_list(struct sk_buff
*skb
, const struct bitmap_port
*map
, u32 id
,
92 return nla_put_net16(skb
, IPSET_ATTR_PORT
,
93 htons(map
->first_port
+ id
));
97 bitmap_port_do_head(struct sk_buff
*skb
, const struct bitmap_port
*map
)
99 return nla_put_net16(skb
, IPSET_ATTR_PORT
, htons(map
->first_port
)) ||
100 nla_put_net16(skb
, IPSET_ATTR_PORT_TO
, htons(map
->last_port
));
104 bitmap_port_kadt(struct ip_set
*set
, const struct sk_buff
*skb
,
105 const struct xt_action_param
*par
,
106 enum ipset_adt adt
, struct ip_set_adt_opt
*opt
)
108 struct bitmap_port
*map
= set
->data
;
109 ipset_adtfn adtfn
= set
->variant
->adt
[adt
];
110 struct bitmap_port_adt_elem e
= { .id
= 0 };
111 struct ip_set_ext ext
= IP_SET_INIT_KEXT(skb
, opt
, set
);
115 if (!ip_set_get_ip_port(skb
, opt
->family
,
116 opt
->flags
& IPSET_DIM_ONE_SRC
, &__port
))
119 port
= ntohs(__port
);
121 if (port
< map
->first_port
|| port
> map
->last_port
)
122 return -IPSET_ERR_BITMAP_RANGE
;
124 e
.id
= port_to_id(map
, port
);
126 return adtfn(set
, &e
, &ext
, &opt
->ext
, opt
->cmdflags
);
130 bitmap_port_uadt(struct ip_set
*set
, struct nlattr
*tb
[],
131 enum ipset_adt adt
, u32
*lineno
, u32 flags
, bool retried
)
133 struct bitmap_port
*map
= set
->data
;
134 ipset_adtfn adtfn
= set
->variant
->adt
[adt
];
135 struct bitmap_port_adt_elem e
= { .id
= 0 };
136 struct ip_set_ext ext
= IP_SET_INIT_UEXT(set
);
137 u32 port
; /* wraparound */
141 if (tb
[IPSET_ATTR_LINENO
])
142 *lineno
= nla_get_u32(tb
[IPSET_ATTR_LINENO
]);
144 if (unlikely(!ip_set_attr_netorder(tb
, IPSET_ATTR_PORT
) ||
145 !ip_set_optattr_netorder(tb
, IPSET_ATTR_PORT_TO
)))
146 return -IPSET_ERR_PROTOCOL
;
148 port
= ip_set_get_h16(tb
[IPSET_ATTR_PORT
]);
149 if (port
< map
->first_port
|| port
> map
->last_port
)
150 return -IPSET_ERR_BITMAP_RANGE
;
151 ret
= ip_set_get_extensions(set
, tb
, &ext
);
155 if (adt
== IPSET_TEST
) {
156 e
.id
= port_to_id(map
, port
);
157 return adtfn(set
, &e
, &ext
, &ext
, flags
);
160 if (tb
[IPSET_ATTR_PORT_TO
]) {
161 port_to
= ip_set_get_h16(tb
[IPSET_ATTR_PORT_TO
]);
162 if (port
> port_to
) {
164 if (port
< map
->first_port
)
165 return -IPSET_ERR_BITMAP_RANGE
;
171 if (port_to
> map
->last_port
)
172 return -IPSET_ERR_BITMAP_RANGE
;
174 for (; port
<= port_to
; port
++) {
175 e
.id
= port_to_id(map
, port
);
176 ret
= adtfn(set
, &e
, &ext
, &ext
, flags
);
178 if (ret
&& !ip_set_eexist(ret
, flags
))
187 bitmap_port_same_set(const struct ip_set
*a
, const struct ip_set
*b
)
189 const struct bitmap_port
*x
= a
->data
;
190 const struct bitmap_port
*y
= b
->data
;
192 return x
->first_port
== y
->first_port
&&
193 x
->last_port
== y
->last_port
&&
194 a
->timeout
== b
->timeout
&&
195 a
->extensions
== b
->extensions
;
200 struct bitmap_port_elem
{
203 #include "ip_set_bitmap_gen.h"
205 /* Create bitmap:ip type of sets */
208 init_map_port(struct ip_set
*set
, struct bitmap_port
*map
,
209 u16 first_port
, u16 last_port
)
211 map
->members
= ip_set_alloc(map
->memsize
);
214 map
->first_port
= first_port
;
215 map
->last_port
= last_port
;
216 set
->timeout
= IPSET_NO_TIMEOUT
;
220 set
->family
= NFPROTO_UNSPEC
;
226 bitmap_port_create(struct net
*net
, struct ip_set
*set
, struct nlattr
*tb
[],
229 struct bitmap_port
*map
;
230 u16 first_port
, last_port
;
233 if (unlikely(!ip_set_attr_netorder(tb
, IPSET_ATTR_PORT
) ||
234 !ip_set_attr_netorder(tb
, IPSET_ATTR_PORT_TO
) ||
235 !ip_set_optattr_netorder(tb
, IPSET_ATTR_TIMEOUT
) ||
236 !ip_set_optattr_netorder(tb
, IPSET_ATTR_CADT_FLAGS
)))
237 return -IPSET_ERR_PROTOCOL
;
239 first_port
= ip_set_get_h16(tb
[IPSET_ATTR_PORT
]);
240 last_port
= ip_set_get_h16(tb
[IPSET_ATTR_PORT_TO
]);
241 if (first_port
> last_port
)
242 swap(first_port
, last_port
);
244 elements
= last_port
- first_port
+ 1;
245 set
->dsize
= ip_set_elem_len(set
, tb
, 0, 0);
246 map
= ip_set_alloc(sizeof(*map
) + elements
* set
->dsize
);
250 map
->elements
= elements
;
251 map
->memsize
= bitmap_bytes(0, map
->elements
);
252 set
->variant
= &bitmap_port
;
253 if (!init_map_port(set
, map
, first_port
, last_port
)) {
257 if (tb
[IPSET_ATTR_TIMEOUT
]) {
258 set
->timeout
= ip_set_timeout_uget(tb
[IPSET_ATTR_TIMEOUT
]);
259 bitmap_port_gc_init(set
, bitmap_port_gc
);
264 static struct ip_set_type bitmap_port_type
= {
265 .name
= "bitmap:port",
266 .protocol
= IPSET_PROTOCOL
,
267 .features
= IPSET_TYPE_PORT
,
268 .dimension
= IPSET_DIM_ONE
,
269 .family
= NFPROTO_UNSPEC
,
270 .revision_min
= IPSET_TYPE_REV_MIN
,
271 .revision_max
= IPSET_TYPE_REV_MAX
,
272 .create
= bitmap_port_create
,
274 [IPSET_ATTR_PORT
] = { .type
= NLA_U16
},
275 [IPSET_ATTR_PORT_TO
] = { .type
= NLA_U16
},
276 [IPSET_ATTR_TIMEOUT
] = { .type
= NLA_U32
},
277 [IPSET_ATTR_CADT_FLAGS
] = { .type
= NLA_U32
},
280 [IPSET_ATTR_PORT
] = { .type
= NLA_U16
},
281 [IPSET_ATTR_PORT_TO
] = { .type
= NLA_U16
},
282 [IPSET_ATTR_TIMEOUT
] = { .type
= NLA_U32
},
283 [IPSET_ATTR_LINENO
] = { .type
= NLA_U32
},
284 [IPSET_ATTR_BYTES
] = { .type
= NLA_U64
},
285 [IPSET_ATTR_PACKETS
] = { .type
= NLA_U64
},
286 [IPSET_ATTR_COMMENT
] = { .type
= NLA_NUL_STRING
,
287 .len
= IPSET_MAX_COMMENT_SIZE
},
288 [IPSET_ATTR_SKBMARK
] = { .type
= NLA_U64
},
289 [IPSET_ATTR_SKBPRIO
] = { .type
= NLA_U32
},
290 [IPSET_ATTR_SKBQUEUE
] = { .type
= NLA_U16
},
296 bitmap_port_init(void)
298 return ip_set_type_register(&bitmap_port_type
);
302 bitmap_port_fini(void)
305 ip_set_type_unregister(&bitmap_port_type
);
308 module_init(bitmap_port_init
);
309 module_exit(bitmap_port_fini
);