Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: ipset: The bitmap types with counter support

Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Jozsef Kadlecsik and committed by
Pablo Neira Ayuso
f48d19db 34d666d4

+186 -15
+13 -1
net/netfilter/ipset/ip_set_bitmap_gen.h
··· 37 37 38 38 #define ext_timeout(e, m) \ 39 39 (unsigned long *)((e) + (m)->offset[IPSET_OFFSET_TIMEOUT]) 40 + #define ext_counter(e, m) \ 41 + (struct ip_set_counter *)((e) + (m)->offset[IPSET_OFFSET_COUNTER]) 40 42 #define get_ext(map, id) ((map)->extensions + (map)->dsize * (id)) 41 43 42 44 static void ··· 93 91 map->memsize + 94 92 map->dsize * map->elements)) || 95 93 (SET_WITH_TIMEOUT(set) && 96 - nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout)))) 94 + nla_put_net32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout))) || 95 + (SET_WITH_COUNTER(set) && 96 + nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, 97 + htonl(IPSET_FLAG_WITH_COUNTERS)))) 97 98 goto nla_put_failure; 98 99 ipset_nest_end(skb, nested); 99 100 ··· 119 114 if (SET_WITH_TIMEOUT(set) && 120 115 ip_set_timeout_expired(ext_timeout(x, map))) 121 116 return 0; 117 + if (SET_WITH_COUNTER(set)) 118 + ip_set_update_counter(ext_counter(x, map), ext, mext, flags); 122 119 return 1; 123 120 } 124 121 ··· 148 141 ip_set_timeout_set(ext_timeout(x, map), ext->timeout); 149 142 #endif 150 143 144 + if (SET_WITH_COUNTER(set)) 145 + ip_set_init_counter(ext_counter(x, map), ext); 151 146 return 0; 152 147 } 153 148 ··· 214 205 goto nla_put_failure; 215 206 #endif 216 207 } 208 + if (SET_WITH_COUNTER(set) && 209 + ip_set_put_counter(skb, ext_counter(x, map))) 210 + goto nla_put_failure; 217 211 ipset_nest_end(skb, nested); 218 212 } 219 213 ipset_nest_end(skb, adt);
+57 -5
net/netfilter/ipset/ip_set_bitmap_ip.c
··· 26 26 #include <linux/netfilter/ipset/ip_set_bitmap.h> 27 27 28 28 #define REVISION_MIN 0 29 - #define REVISION_MAX 0 29 + #define REVISION_MAX 1 /* Counter support added */ 30 30 31 31 MODULE_LICENSE("GPL"); 32 32 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); ··· 137 137 int ret = 0; 138 138 139 139 if (unlikely(!tb[IPSET_ATTR_IP] || 140 - !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 140 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 141 + !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 142 + !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES))) 141 143 return -IPSET_ERR_PROTOCOL; 142 144 143 145 if (tb[IPSET_ATTR_LINENO]) ··· 215 213 unsigned long timeout; 216 214 }; 217 215 216 + /* Plain variant with counter */ 217 + 218 + struct bitmap_ipc_elem { 219 + struct ip_set_counter counter; 220 + }; 221 + 222 + /* Timeout variant with counter */ 223 + 224 + struct bitmap_ipct_elem { 225 + unsigned long timeout; 226 + struct ip_set_counter counter; 227 + }; 228 + 218 229 #include "ip_set_bitmap_gen.h" 219 230 220 231 /* Create bitmap:ip type of sets */ ··· 264 249 bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags) 265 250 { 266 251 struct bitmap_ip *map; 267 - u32 first_ip, last_ip, hosts; 252 + u32 first_ip, last_ip, hosts, cadt_flags = 0; 268 253 u64 elements; 269 254 u8 netmask = 32; 270 255 int ret; 271 256 272 257 if (unlikely(!tb[IPSET_ATTR_IP] || 273 - !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 258 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 259 + !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS))) 274 260 return -IPSET_ERR_PROTOCOL; 275 261 276 262 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &first_ip); ··· 336 320 337 321 map->memsize = bitmap_bytes(0, elements - 1); 338 322 set->variant = &bitmap_ip; 339 - if (tb[IPSET_ATTR_TIMEOUT]) { 323 + if (tb[IPSET_ATTR_CADT_FLAGS]) 324 + cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 325 + if (cadt_flags & IPSET_FLAG_WITH_COUNTERS) { 326 + set->extensions |= IPSET_EXT_COUNTER; 327 + if (tb[IPSET_ATTR_TIMEOUT]) { 328 + map->dsize = sizeof(struct bitmap_ipct_elem); 329 + map->offset[IPSET_OFFSET_TIMEOUT] = 330 + offsetof(struct bitmap_ipct_elem, timeout); 331 + map->offset[IPSET_OFFSET_COUNTER] = 332 + offsetof(struct bitmap_ipct_elem, counter); 333 + 334 + if (!init_map_ip(set, map, first_ip, last_ip, 335 + elements, hosts, netmask)) { 336 + kfree(map); 337 + return -ENOMEM; 338 + } 339 + 340 + map->timeout = ip_set_timeout_uget( 341 + tb[IPSET_ATTR_TIMEOUT]); 342 + set->extensions |= IPSET_EXT_TIMEOUT; 343 + 344 + bitmap_ip_gc_init(set, bitmap_ip_gc); 345 + } else { 346 + map->dsize = sizeof(struct bitmap_ipc_elem); 347 + map->offset[IPSET_OFFSET_COUNTER] = 348 + offsetof(struct bitmap_ipc_elem, counter); 349 + 350 + if (!init_map_ip(set, map, first_ip, last_ip, 351 + elements, hosts, netmask)) { 352 + kfree(map); 353 + return -ENOMEM; 354 + } 355 + } 356 + } else if (tb[IPSET_ATTR_TIMEOUT]) { 340 357 map->dsize = sizeof(struct bitmap_ipt_elem); 341 358 map->offset[IPSET_OFFSET_TIMEOUT] = 342 359 offsetof(struct bitmap_ipt_elem, timeout); ··· 410 361 [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, 411 362 [IPSET_ATTR_NETMASK] = { .type = NLA_U8 }, 412 363 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 364 + [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, 413 365 }, 414 366 .adt_policy = { 415 367 [IPSET_ATTR_IP] = { .type = NLA_NESTED }, ··· 418 368 [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, 419 369 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 420 370 [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, 371 + [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, 372 + [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, 421 373 }, 422 374 .me = THIS_MODULE, 423 375 };
+63 -5
net/netfilter/ipset/ip_set_bitmap_ipmac.c
··· 26 26 #include <linux/netfilter/ipset/ip_set_bitmap.h> 27 27 28 28 #define REVISION_MIN 0 29 - #define REVISION_MAX 0 29 + #define REVISION_MAX 1 /* Counter support added */ 30 30 31 31 MODULE_LICENSE("GPL"); 32 32 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); ··· 250 250 int ret = 0; 251 251 252 252 if (unlikely(!tb[IPSET_ATTR_IP] || 253 - !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 253 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 254 + !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 255 + !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES))) 254 256 return -IPSET_ERR_PROTOCOL; 255 257 256 258 if (tb[IPSET_ATTR_LINENO]) ··· 301 299 unsigned long timeout; 302 300 }; 303 301 302 + /* Plain variant with counter */ 303 + 304 + struct bitmap_ipmacc_elem { 305 + struct { 306 + unsigned char ether[ETH_ALEN]; 307 + unsigned char filled; 308 + } __attribute__ ((aligned)); 309 + struct ip_set_counter counter; 310 + }; 311 + 312 + /* Timeout variant with counter */ 313 + 314 + struct bitmap_ipmacct_elem { 315 + struct { 316 + unsigned char ether[ETH_ALEN]; 317 + unsigned char filled; 318 + } __attribute__ ((aligned)); 319 + unsigned long timeout; 320 + struct ip_set_counter counter; 321 + }; 322 + 304 323 #include "ip_set_bitmap_gen.h" 305 324 306 325 /* Create bitmap:ip,mac type of sets */ ··· 355 332 bitmap_ipmac_create(struct ip_set *set, struct nlattr *tb[], 356 333 u32 flags) 357 334 { 358 - u32 first_ip, last_ip; 335 + u32 first_ip, last_ip, cadt_flags = 0; 359 336 u64 elements; 360 337 struct bitmap_ipmac *map; 361 338 int ret; 362 339 363 340 if (unlikely(!tb[IPSET_ATTR_IP] || 364 - !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 341 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 342 + !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS))) 365 343 return -IPSET_ERR_PROTOCOL; 366 344 367 345 ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &first_ip); ··· 399 375 400 376 map->memsize = bitmap_bytes(0, elements - 1); 401 377 set->variant = &bitmap_ipmac; 402 - if (tb[IPSET_ATTR_TIMEOUT]) { 378 + if (tb[IPSET_ATTR_CADT_FLAGS]) 379 + cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 380 + if (cadt_flags & IPSET_FLAG_WITH_COUNTERS) { 381 + set->extensions |= IPSET_EXT_COUNTER; 382 + if (tb[IPSET_ATTR_TIMEOUT]) { 383 + map->dsize = sizeof(struct bitmap_ipmacct_elem); 384 + map->offset[IPSET_OFFSET_TIMEOUT] = 385 + offsetof(struct bitmap_ipmacct_elem, timeout); 386 + map->offset[IPSET_OFFSET_COUNTER] = 387 + offsetof(struct bitmap_ipmacct_elem, counter); 388 + 389 + if (!init_map_ipmac(set, map, first_ip, last_ip, 390 + elements)) { 391 + kfree(map); 392 + return -ENOMEM; 393 + } 394 + map->timeout = ip_set_timeout_uget( 395 + tb[IPSET_ATTR_TIMEOUT]); 396 + set->extensions |= IPSET_EXT_TIMEOUT; 397 + bitmap_ipmac_gc_init(set, bitmap_ipmac_gc); 398 + } else { 399 + map->dsize = sizeof(struct bitmap_ipmacc_elem); 400 + map->offset[IPSET_OFFSET_COUNTER] = 401 + offsetof(struct bitmap_ipmacc_elem, counter); 402 + 403 + if (!init_map_ipmac(set, map, first_ip, last_ip, 404 + elements)) { 405 + kfree(map); 406 + return -ENOMEM; 407 + } 408 + } 409 + } else if (tb[IPSET_ATTR_TIMEOUT]) { 403 410 map->dsize = sizeof(struct bitmap_ipmact_elem); 404 411 map->offset[IPSET_OFFSET_TIMEOUT] = 405 412 offsetof(struct bitmap_ipmact_elem, timeout); ··· 468 413 [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, 469 414 [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, 470 415 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 416 + [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, 471 417 }, 472 418 .adt_policy = { 473 419 [IPSET_ATTR_IP] = { .type = NLA_NESTED }, ··· 476 420 .len = ETH_ALEN }, 477 421 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 478 422 [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, 423 + [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, 424 + [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, 479 425 }, 480 426 .me = THIS_MODULE, 481 427 };
+53 -4
net/netfilter/ipset/ip_set_bitmap_port.c
··· 21 21 #include <linux/netfilter/ipset/ip_set_getport.h> 22 22 23 23 #define REVISION_MIN 0 24 - #define REVISION_MAX 0 24 + #define REVISION_MAX 1 /* Counter support added */ 25 25 26 26 MODULE_LICENSE("GPL"); 27 27 MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); ··· 138 138 139 139 if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || 140 140 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || 141 - !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 141 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 142 + !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 143 + !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES))) 142 144 return -IPSET_ERR_PROTOCOL; 143 145 144 146 if (tb[IPSET_ATTR_LINENO]) ··· 201 199 }; 202 200 203 201 /* Timeout variant */ 202 + 204 203 struct bitmap_portt_elem { 205 204 unsigned long timeout; 205 + }; 206 + 207 + /* Plain variant with counter */ 208 + 209 + struct bitmap_portc_elem { 210 + struct ip_set_counter counter; 211 + }; 212 + 213 + /* Timeout variant with counter */ 214 + 215 + struct bitmap_portct_elem { 216 + unsigned long timeout; 217 + struct ip_set_counter counter; 206 218 }; 207 219 208 220 #include "ip_set_bitmap_gen.h" ··· 252 236 { 253 237 struct bitmap_port *map; 254 238 u16 first_port, last_port; 239 + u32 cadt_flags = 0; 255 240 256 241 if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || 257 242 !ip_set_attr_netorder(tb, IPSET_ATTR_PORT_TO) || 258 - !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) 243 + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 244 + !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS))) 259 245 return -IPSET_ERR_PROTOCOL; 260 246 261 247 first_port = ip_set_get_h16(tb[IPSET_ATTR_PORT]); ··· 276 258 map->elements = last_port - first_port + 1; 277 259 map->memsize = map->elements * sizeof(unsigned long); 278 260 set->variant = &bitmap_port; 279 - if (tb[IPSET_ATTR_TIMEOUT]) { 261 + if (tb[IPSET_ATTR_CADT_FLAGS]) 262 + cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); 263 + if (cadt_flags & IPSET_FLAG_WITH_COUNTERS) { 264 + set->extensions |= IPSET_EXT_COUNTER; 265 + if (tb[IPSET_ATTR_TIMEOUT]) { 266 + map->dsize = sizeof(struct bitmap_portct_elem); 267 + map->offset[IPSET_OFFSET_TIMEOUT] = 268 + offsetof(struct bitmap_portct_elem, timeout); 269 + map->offset[IPSET_OFFSET_COUNTER] = 270 + offsetof(struct bitmap_portct_elem, counter); 271 + if (!init_map_port(set, map, first_port, last_port)) { 272 + kfree(map); 273 + return -ENOMEM; 274 + } 275 + 276 + map->timeout = 277 + ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 278 + set->extensions |= IPSET_EXT_TIMEOUT; 279 + bitmap_port_gc_init(set, bitmap_port_gc); 280 + } else { 281 + map->dsize = sizeof(struct bitmap_portc_elem); 282 + map->offset[IPSET_OFFSET_COUNTER] = 283 + offsetof(struct bitmap_portc_elem, counter); 284 + if (!init_map_port(set, map, first_port, last_port)) { 285 + kfree(map); 286 + return -ENOMEM; 287 + } 288 + } 289 + } else if (tb[IPSET_ATTR_TIMEOUT]) { 280 290 map->dsize = sizeof(struct bitmap_portt_elem); 281 291 map->offset[IPSET_OFFSET_TIMEOUT] = 282 292 offsetof(struct bitmap_portt_elem, timeout); ··· 340 294 [IPSET_ATTR_PORT] = { .type = NLA_U16 }, 341 295 [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 }, 342 296 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 297 + [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, 343 298 }, 344 299 .adt_policy = { 345 300 [IPSET_ATTR_PORT] = { .type = NLA_U16 }, 346 301 [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 }, 347 302 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, 348 303 [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, 304 + [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, 305 + [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, 349 306 }, 350 307 .me = THIS_MODULE, 351 308 };