From ac0e5da3166da201ea00fd7f3cd927b0a49d8fef Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Thu, 22 Apr 2010 17:07:48 +0200 Subject: Seventh stage to ipset-5 Refresh existing files in kernel/ with new content and add some new include/source files. --- kernel/include/linux/netfilter/ip_set_timeout.h | 103 ++++++ kernel/include/net/pfxlen.h | 295 +++++++++++++++ kernel/ip_set_hash_ip_src.c | 473 ++++++++++++++++++++++++ 3 files changed, 871 insertions(+) create mode 100644 kernel/include/linux/netfilter/ip_set_timeout.h create mode 100644 kernel/include/net/pfxlen.h create mode 100644 kernel/ip_set_hash_ip_src.c (limited to 'kernel') diff --git a/kernel/include/linux/netfilter/ip_set_timeout.h b/kernel/include/linux/netfilter/ip_set_timeout.h new file mode 100644 index 0000000..da18875 --- /dev/null +++ b/kernel/include/linux/netfilter/ip_set_timeout.h @@ -0,0 +1,103 @@ +#ifndef _IP_SET_TIMEOUT_H +#define _IP_SET_TIMEOUT_H + +/* Copyright (C) 2003-2010 Jozsef Kadlecsik + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifdef __KERNEL__ + +/* How often should the gc be run at a minimum */ +#define IPSET_GC_TIME (3 * 60) + +/* Timeout period depending on the timeout value of the given set */ +#define IPSET_GC_PERIOD(timeout) \ + max_t(uint32_t, (timeout)/10, IPSET_GC_TIME) + +/* How much msec to sleep before retrying to destroy gc timer */ +#define IPSET_DESTROY_TIMER_SLEEP 10 + +/* Timing out etries: unset and permanent */ +#define IPSET_ELEM_UNSET 0 +#define IPSET_ELEM_PERMANENT UINT_MAX/2 + +#ifdef IP_SET_BITMAP_TIMEOUT +static inline bool +ip_set_timeout_test(unsigned long timeout) +{ + return timeout != IPSET_ELEM_UNSET + && (timeout == IPSET_ELEM_PERMANENT + || time_after(timeout, jiffies)); +} + +static inline bool +ip_set_timeout_expired(unsigned long timeout) +{ + return timeout != IPSET_ELEM_UNSET + && timeout != IPSET_ELEM_PERMANENT + && time_before(timeout, jiffies); +} + +static inline unsigned long +ip_set_timeout_set(uint32_t timeout) +{ + unsigned long t; + + if (!timeout) + return IPSET_ELEM_PERMANENT; + + t = timeout * HZ + jiffies; + if (t == IPSET_ELEM_UNSET || t == IPSET_ELEM_PERMANENT) + t++; + + return t; +} + +static inline uint32_t +ip_set_timeout_get(unsigned long timeout) +{ + return timeout == IPSET_ELEM_PERMANENT ? 0 : (timeout - jiffies)/HZ; +} + +#else + +static inline bool +ip_set_timeout_test(unsigned long timeout) +{ + return timeout == IPSET_ELEM_UNSET || time_after(timeout, jiffies); +} + +static inline bool +ip_set_timeout_expired(unsigned long timeout) +{ + return timeout != IPSET_ELEM_UNSET && time_before(timeout, jiffies); +} + +static inline unsigned long +ip_set_timeout_set(uint32_t timeout) +{ + unsigned long t; + + if (!timeout) + return IPSET_ELEM_UNSET; + + t = timeout * HZ + jiffies; + if (t == IPSET_ELEM_UNSET) + t++; + + return t; +} + +static inline uint32_t +ip_set_timeout_get(unsigned long timeout) +{ + return timeout == IPSET_ELEM_UNSET ? 0 : (timeout - jiffies)/HZ; +} +#endif /* IP_SET_BITMAP_TIMEOUT */ + +#endif /* __KERNEL__ */ + +#endif /*_IP_SET_TIMEOUT_H */ diff --git a/kernel/include/net/pfxlen.h b/kernel/include/net/pfxlen.h new file mode 100644 index 0000000..8183e17 --- /dev/null +++ b/kernel/include/net/pfxlen.h @@ -0,0 +1,295 @@ +#ifndef _NET_PFXLEN_H +#define _NET_PFXLEN_H 1 + +#include +#include /* union nf_inet_addr */ + +#define E(a, b, c, d) \ + {.ip6 = { \ + __constant_htonl(a), __constant_htonl(b), \ + __constant_htonl(c), __constant_htonl(d), \ + }} + +/* + * This table works for both IPv4 and IPv6; + * just use prefixlen_netmask_map[prefixlength].ip. + */ +const union nf_inet_addr prefixlen_netmask_map[] = { + E(0x00000000, 0x00000000, 0x00000000, 0x00000000), + E(0x80000000, 0x00000000, 0x00000000, 0x00000000), + E(0xC0000000, 0x00000000, 0x00000000, 0x00000000), + E(0xE0000000, 0x00000000, 0x00000000, 0x00000000), + E(0xF0000000, 0x00000000, 0x00000000, 0x00000000), + E(0xF8000000, 0x00000000, 0x00000000, 0x00000000), + E(0xFC000000, 0x00000000, 0x00000000, 0x00000000), + E(0xFE000000, 0x00000000, 0x00000000, 0x00000000), + E(0xFF000000, 0x00000000, 0x00000000, 0x00000000), + E(0xFF800000, 0x00000000, 0x00000000, 0x00000000), + E(0xFFC00000, 0x00000000, 0x00000000, 0x00000000), + E(0xFFE00000, 0x00000000, 0x00000000, 0x00000000), + E(0xFFF00000, 0x00000000, 0x00000000, 0x00000000), + E(0xFFF80000, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFC0000, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFE0000, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFF0000, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFF8000, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFFC000, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFFE000, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFFF000, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFFF800, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFFFC00, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFFFE00, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFFFF00, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFFFF80, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFFFFC0, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFFFFE0, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFFFFF0, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFFFFF8, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFFFFFC, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFFFFFE, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0x80000000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xC0000000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xE0000000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xF0000000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xF8000000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFC000000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFE000000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFF000000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFF800000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFC00000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFE00000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFF00000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFF80000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFC0000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFE0000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFF0000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFF8000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFC000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFE000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFF000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFF800, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFC00, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFE00, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFF00, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFF80, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFC0, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFE0, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFF0, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFF8, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFC, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFE, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0x80000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xC0000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xE0000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xF0000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xF8000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFC000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFE000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFF800000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFC00000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFE00000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFF00000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFF80000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFC0000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFE0000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF0000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF8000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFC000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF800, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFC00, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFE00, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF00, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF80, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFC0, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFE0, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF0, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF8, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFC, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x80000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xC0000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xE0000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xF0000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xF8000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFC000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFE000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF800000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFC00000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFE00000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFF00000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFF80000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFC0000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFE0000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF0000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF8000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFC000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF800), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFC00), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFE00), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF00), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF80), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFC0), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFE0), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF0), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF8), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFC), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF), +}; + +#define NETMASK(n) prefixlen_netmask_map[n].ip +#define NETMASK6(n) prefixlen_netmask_map[n].ip6 + +#undef E +#define E(a, b, c, d) \ + {.ip6 = { a, b, c, d } } + +/* + * This table works for both IPv4 and IPv6; + * just use prefixlen_netmask_map[prefixlength].ip. + */ +const union nf_inet_addr prefixlen_hostmask_map[] = { + E(0x00000000, 0x00000000, 0x00000000, 0x00000000), + E(0x80000000, 0x00000000, 0x00000000, 0x00000000), + E(0xC0000000, 0x00000000, 0x00000000, 0x00000000), + E(0xE0000000, 0x00000000, 0x00000000, 0x00000000), + E(0xF0000000, 0x00000000, 0x00000000, 0x00000000), + E(0xF8000000, 0x00000000, 0x00000000, 0x00000000), + E(0xFC000000, 0x00000000, 0x00000000, 0x00000000), + E(0xFE000000, 0x00000000, 0x00000000, 0x00000000), + E(0xFF000000, 0x00000000, 0x00000000, 0x00000000), + E(0xFF800000, 0x00000000, 0x00000000, 0x00000000), + E(0xFFC00000, 0x00000000, 0x00000000, 0x00000000), + E(0xFFE00000, 0x00000000, 0x00000000, 0x00000000), + E(0xFFF00000, 0x00000000, 0x00000000, 0x00000000), + E(0xFFF80000, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFC0000, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFE0000, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFF0000, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFF8000, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFFC000, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFFE000, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFFF000, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFFF800, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFFFC00, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFFFE00, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFFFF00, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFFFF80, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFFFFC0, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFFFFE0, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFFFFF0, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFFFFF8, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFFFFFC, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFFFFFE, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0x80000000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xC0000000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xE0000000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xF0000000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xF8000000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFC000000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFE000000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFF000000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFF800000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFC00000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFE00000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFF00000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFF80000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFC0000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFE0000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFF0000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFF8000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFC000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFE000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFF000, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFF800, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFC00, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFE00, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFF00, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFF80, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFC0, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFE0, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFF0, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFF8, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFC, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFE, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0x80000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xC0000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xE0000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xF0000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xF8000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFC000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFE000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFF800000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFC00000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFE00000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFF00000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFF80000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFC0000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFE0000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF0000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF8000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFC000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF000, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF800, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFC00, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFE00, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF00, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF80, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFC0, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFE0, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF0, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF8, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFC, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x80000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xC0000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xE0000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xF0000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xF8000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFC000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFE000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF800000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFC00000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFE00000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFF00000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFF80000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFC0000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFE0000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF0000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF8000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFC000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF000), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF800), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFC00), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFE00), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF00), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF80), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFC0), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFE0), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF0), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF8), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFC), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE), + E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF), +}; + +#define HOSTMASK(n) prefixlen_hostmask_map[n].ip +#define HOSTMASK6(n) prefixlen_hostmask_map[n].ip6 + +#endif /* _NET_PFXLEN_H */ diff --git a/kernel/ip_set_hash_ip_src.c b/kernel/ip_set_hash_ip_src.c new file mode 100644 index 0000000..ef0a8ec --- /dev/null +++ b/kernel/ip_set_hash_ip_src.c @@ -0,0 +1,473 @@ +/* Copyright (C) 2003-2010 Jozsef Kadlecsik + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#define CONCAT(a, b, c) a##b##c +#define TOKEN(a, b, c) CONCAT(a, b, c) + +/* IPv4/IPv6 dependent function prototypes for hash:ip */ + +#if PF == 4 +#define HOST_MASK 32 +#define NLA_PUT_ADDR(skb, ip) \ + NLA_PUT_NET32(skb, IPSET_ATTR_IP, *(ip)); +#else +#define HOST_MASK 128 +#define NLA_PUT_ADDR(skb, ip) \ + NLA_PUT(skb, IPSET_ATTR_IP, sizeof(struct in6_addr), ip); +#endif + +#define hash_ip_pf_timeout TOKEN(hash_ip, PF, _timeout) +#define hash_ip_pf_expired TOKEN(hash_ip, PF, _expired) +#define hash_ip_pf_elem_test TOKEN(hash_ip, PF, _elem_test) +#define hash_ip_pf_elem_exist TOKEN(hash_ip, PF, _elem_exist) +#define hash_ip_pf_elem_expired TOKEN(hash_ip, PF, _elem_expired) +#define hash_ip_pf_test TOKEN(hash_ip, PF, _test) +#define hash_ip_pf_add TOKEN(hash_ip, PF, _add) +#define hash_ip_pf_readd TOKEN(hash_ip, PF, _readd) +#define hash_ip_pf_del TOKEN(hash_ip, PF, _del) +#define hash_ip_pf_map_expired TOKEN(hash_ip, PF, _map_expired) +#define hash_ip_pf_set_expired TOKEN(hash_ip, PF, _set_expired) +#define hash_ip_pf_head TOKEN(hash_ip, PF, _head) +#define hash_ip_pf_list TOKEN(hash_ip, PF, _list) +#define hash_ip_pf_resize TOKEN(hash_ip, PF, _resize) +#define hash_ip_pf TOKEN(hash_ip, PF , ) +#define hash_ip_pf_kadt TOKEN(hash_ip, PF, _kadt) +#define hash_ip_pf_uadt TOKEN(hash_ip, PF, _uadt) +#define hash_ip_pf_destroy TOKEN(hash_ip, PF, _destroy) +#define hash_ip_pf_flush TOKEN(hash_ip, PF, _flush) +#define hash_ip_pf_timeout_gc TOKEN(hash_ip, PF, _timeout_gc) +#define hash_ip_pf_gc_init TOKEN(hash_ip, PF, _gc_init) +#define ip_pf_hash TOKEN(ip, PF, _hash) +#define ip_pf_cmp TOKEN(ip, PF, _cmp) +#define ip_pf_null TOKEN(ip, PF, _null) +#define ip_pf_cpy TOKEN(ip, PF, _cpy) +#define ip_pf_zero_out TOKEN(ip, PF, _zero_out) +#define ip_pf_elem TOKEN(ip, PF, _elem) +#define ip_pf_elem_timeout TOKEN(ip, PF, _elem_timeout) +#define ip_pf_get_elem_timeout TOKEN(get_ip, PF, _elem_timeout) + +static inline bool +hash_ip_pf_timeout(const struct hash_ip *map, uint32_t id) +{ + struct ip_pf_elem_timeout *elem = hash_ip_elem(map, id); + + return ip_set_timeout_test(elem->timeout); +} + +static inline bool +hash_ip_pf_expired(const struct hash_ip *map, uint32_t id) +{ + struct ip_pf_elem_timeout *elem = hash_ip_elem(map, id); + + return ip_set_timeout_expired(elem->timeout); +} + +static inline bool +hash_ip_pf_elem_test(const struct hash_ip *map, bool with_timeout, + uint32_t id, struct ip_pf_elem * ip) +{ + struct ip_pf_elem *elem = hash_ip_elem(map, id); + + return ip_pf_cmp(elem, ip) + && (!with_timeout || hash_ip_pf_timeout(map, id)); +} + +static inline bool +hash_ip_pf_elem_exist(const struct hash_ip *map, bool with_timeout, + uint32_t id) +{ + struct ip_pf_elem *elem = hash_ip_elem(map, id); + + return !(ip_pf_null(elem) + || (with_timeout && hash_ip_pf_expired(map, id))); +} + +static inline bool +hash_ip_pf_elem_expired(const struct hash_ip *map, bool with_timeout, + uint32_t id) +{ + struct ip_pf_elem *elem = hash_ip_elem(map, id); + + return ip_pf_null(elem) + || (with_timeout && hash_ip_pf_expired(map, id)); +} + +static inline uint32_t +hash_ip_pf_test(const struct hash_ip *map, bool with_timeout, + struct ip_pf_elem * ip) +{ + uint32_t id; + uint8_t i; + + for (i = 0; i < map->probes; i++) { + id = ip_pf_hash(ip, *(map->initval + i), map->hashsize); + if (hash_ip_pf_elem_test(map, with_timeout, id, ip)) + return id + 1; + /* No shortcut - there can be deleted entries. */ + } + return 0; +} + +static void +hash_ip_pf_map_expired(struct hash_ip *map) +{ + struct ip_pf_elem_timeout *table = map->members; + uint32_t i; + + /* We run parallel with other readers (test element) + * but adding/deleting new entries is locked out */ + for (i = 0; i < map->hashsize; i++) + if (ip_set_timeout_expired(table[i].timeout)) { + ip_pf_zero_out((struct ip_pf_elem *)&table[i]); + table[i].timeout = IPSET_ELEM_UNSET; + map->elements--; + } +} + +static inline void +hash_ip_pf_set_expired(struct ip_set *set) +{ + /* We run parallel with other readers (test element) + * but adding/deleting new entries is locked out */ + read_lock_bh(&set->lock); + hash_ip_pf_map_expired(set->data); + read_unlock_bh(&set->lock); +} + +static int +hash_ip_pf_add(struct hash_ip *map, bool with_timeout, + struct ip_pf_elem *ip, uint32_t timeout) +{ + uint32_t id, empty = 0; + uint8_t i; + + if (map->elements >= map->maxelem) { + if (with_timeout) { + hash_ip_pf_map_expired(map); + if (map->elements < map->maxelem) + goto doit; + } + return -IPSET_ERR_HASH_FULL; + } + +doit: + for (i = 0; i < map->probes; i++) { + id = ip_pf_hash(ip, *(map->initval + i), map->hashsize); + if (hash_ip_pf_elem_test(map, with_timeout, id, ip)) + return -IPSET_ERR_EXIST; + if (empty == 0 + && hash_ip_pf_elem_expired(map, with_timeout, id)) + empty = id + 1; + /* There can be deleted entries, must check all slots */ + } + if (!empty) + /* Trigger rehashing */ + return -EAGAIN; + + if (with_timeout) { + struct ip_pf_elem_timeout *e = hash_ip_elem(map, empty - 1); + e->timeout = ip_set_timeout_set(timeout); + D("add with timeout: %u (%lu)", timeout, e->timeout); + ip_pf_cpy((struct ip_pf_elem *)e, ip); + } else { + struct ip_pf_elem *e = hash_ip_elem(map, empty - 1); + ip_pf_cpy(e, ip); + } + map->elements++; + return 0; +} + +static int +hash_ip_pf_readd(struct hash_ip *map, bool with_timeout, struct ip_pf_elem *ip) +{ + uint32_t id, empty = 0; + uint8_t i; + + for (i = 0; empty == 0 && i < map->probes; i++) { + id = ip_pf_hash(ip, *(map->initval + i), map->hashsize); + if (ip_pf_null(hash_ip_elem(map, id))) + empty = id + 1; + } + if (!empty) + /* Trigger rehashing */ + return -EAGAIN; + + if (with_timeout) { + struct ip_pf_elem_timeout *e = hash_ip_elem(map, empty - 1); + e->timeout = ip_pf_get_elem_timeout(ip); + ip_pf_cpy((struct ip_pf_elem *)e, ip); + } else { + struct ip_pf_elem *e = hash_ip_elem(map, empty - 1); + ip_pf_cpy(e, ip); + } + map->elements++; + return 0; +} + +static int +hash_ip_pf_del(struct hash_ip *map, bool with_timeout, struct ip_pf_elem *ip) +{ + struct ip_pf_elem *e; + uint32_t id, found = 0; + uint8_t i; + + for (i = 0; i < map->probes; i++) { + id = ip_pf_hash(ip, *(map->initval + i), map->hashsize); + if (hash_ip_pf_elem_test(map, with_timeout, id, ip)) { + found = id + 1; + break; + } + } + if (!found) + return -IPSET_ERR_EXIST; + + e = hash_ip_elem(map, found - 1); + ip_pf_zero_out(e); + if (with_timeout) + ((struct ip_pf_elem_timeout *)e)->timeout = IPSET_ELEM_UNSET; + + map->elements--; + + return 0; +} + +static int +hash_ip_pf_head(struct ip_set *set, struct sk_buff *skb) +{ + const struct hash_ip *map = set->data; + struct nlattr *nested; + + if (set->flags & IP_SET_FLAG_TIMEOUT) + hash_ip_pf_set_expired(set); + + nested = ipset_nest_start(skb, IPSET_ATTR_DATA); + if (!nested) + goto nla_put_failure; + NLA_PUT_NET32(skb, IPSET_ATTR_HASHSIZE, htonl(map->hashsize)); + NLA_PUT_NET32(skb, IPSET_ATTR_MAXELEM, htonl(map->maxelem)); + if (map->netmask != HOST_MASK) + NLA_PUT_U8(skb, IPSET_ATTR_NETMASK, map->netmask); + NLA_PUT_U8(skb, IPSET_ATTR_PROBES, map->probes); + NLA_PUT_U8(skb, IPSET_ATTR_RESIZE, map->resize); + NLA_PUT_NET32(skb, IPSET_ATTR_ELEMENTS, htonl(map->elements)); + NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, + htonl(atomic_read(&set->ref) - 1)); + NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, + htonl(map->hashsize * map->elem_size)); + if (set->flags & IP_SET_FLAG_TIMEOUT) + NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout)); + ipset_nest_end(skb, nested); + + return 0; +nla_put_failure: + return -EFAULT; +} + +static int +hash_ip_pf_list(struct ip_set *set, + struct sk_buff *skb, struct netlink_callback *cb) +{ + const struct hash_ip *map = set->data; + struct nlattr *atd, *nested; + struct ip_pf_elem *elem; + uint32_t id, first = cb->args[2]; + bool with_timeout = set->flags & IP_SET_FLAG_TIMEOUT; + + atd = ipset_nest_start(skb, IPSET_ATTR_ADT); + if (!atd) + return -EFAULT; + for (; cb->args[2] < map->hashsize; cb->args[2]++) { + id = cb->args[2]; + if (hash_ip_pf_elem_expired(map, with_timeout, id)) + continue; + nested = ipset_nest_start(skb, IPSET_ATTR_DATA); + if (!nested) { + if (id == first) { + nla_nest_cancel(skb, atd); + return -EFAULT; + } else + goto nla_put_failure; + } + elem = hash_ip_elem(map, id); + NLA_PUT_ADDR(skb, &elem->ip); + if (map->netmask != HOST_MASK) + NLA_PUT_U8(skb, IPSET_ATTR_CIDR, map->netmask); + if (with_timeout) { + unsigned long timeout = ip_pf_get_elem_timeout(elem); + D("list with timeout: %u (%lu)", + ip_set_timeout_get(timeout), timeout); + NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, + htonl(ip_set_timeout_get(timeout))); + } + ipset_nest_end(skb, nested); + } + ipset_nest_end(skb, atd); + /* Set listing finished */ + cb->args[2] = 0; + + return 0; + +nla_put_failure: + nla_nest_cancel(skb, nested); + ipset_nest_end(skb, atd); + return 0; +} + +static int +hash_ip_pf_resize(struct ip_set *set, uint8_t retried) +{ + struct hash_ip *map = set->data, *tmp; + void *members; + uint32_t i, hashsize = map->hashsize; + uint8_t oflags, flags = set->flags; + bool with_timeout = flags & IP_SET_FLAG_TIMEOUT; + int ret; + + if (map->resize == 0) + return -IPSET_ERR_HASH_FULL; + + /* Try to cleanup first */ + if (retried == 0 && with_timeout) { + i = map->elements; + hash_ip_pf_set_expired(set); + if (map->elements < i) + return 0; + } + +again: + ret = 0; + + /* Calculate new hash size */ + hashsize += (hashsize * map->resize)/100; + if (hashsize == map->hashsize) + hashsize++; + if (hashsize >= map->maxelem) + return -IPSET_ERR_HASH_FULL; + + printk("Rehashing of set %s triggered: hash grows from %lu to %lu\n", + set->name, + (long unsigned)map->hashsize, + (long unsigned)hashsize); + + tmp = kmalloc(sizeof(struct hash_ip) + + map->probes * sizeof(initval_t), GFP_ATOMIC); + if (!tmp) + return -ENOMEM; + + memcpy(tmp, map, sizeof(*map) + map->probes * sizeof(initval_t)); + tmp->elements = 0; + tmp->hashsize = hashsize; + tmp->members = ip_set_alloc(hashsize * map->elem_size, + GFP_ATOMIC, &flags); + if (!tmp->members) { + kfree(tmp); + return -ENOMEM; + } + + write_lock_bh(&set->lock); + map = set->data; /* Play safe */ + for (i = 0; i < map->hashsize && ret == 0; i++) { + if (hash_ip_pf_elem_exist(map, with_timeout, i)) + ret = hash_ip_pf_readd(tmp, with_timeout, + hash_ip_elem(map, i)); + } + if (ret) { + /* Failure, try again */ + write_unlock_bh(&set->lock); + ip_set_free(tmp->members, flags); + kfree(tmp); + goto again; + } + + /* Success at resizing! */ + members = map->members; + oflags = set->flags; + + map->hashsize = tmp->hashsize; + map->members = tmp->members; + map->elements = tmp->elements; + set->flags = flags; + write_unlock_bh(&set->lock); + + ip_set_free(members, oflags); + kfree(tmp); + + return 0; +} + +static int +hash_ip_pf_kadt(struct ip_set *set, const struct sk_buff * skb, + enum ipset_adt adt, uint8_t pf, const uint8_t *flags); +static int +hash_ip_pf_uadt(struct ip_set *set, struct nlattr *head, int len, + enum ipset_adt adt, uint32_t *lineno, uint32_t flags); + +static const struct ip_set_type_variant hash_ip_pf __read_mostly = { + .kadt = hash_ip_pf_kadt, + .uadt = hash_ip_pf_uadt, + .destroy = hash_ip_pf_destroy, + .flush = hash_ip_pf_flush, + .head = hash_ip_pf_head, + .list = hash_ip_pf_list, + .resize = hash_ip_pf_resize, +}; + +static void +hash_ip_pf_timeout_gc(unsigned long ul_set) +{ + struct ip_set *set = (struct ip_set *) ul_set; + struct hash_ip *map = set->data; + + hash_ip_pf_set_expired(set); + + map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ; + add_timer(&map->gc); +} + +static inline void +hash_ip_pf_gc_init(struct ip_set *set) +{ + struct hash_ip *map = set->data; + + init_timer(&map->gc); + map->gc.data = (unsigned long) set; + map->gc.function = hash_ip_pf_timeout_gc; + map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ; + add_timer(&map->gc); +} + +#undef HOST_MASK +#undef NLA_PUT_ADDR +#undef hash_ip_pf_timeout +#undef hash_ip_pf_expired +#undef hash_ip_pf_elem_test +#undef hash_ip_pf_elem_exist +#undef hash_ip_pf_elem_expired +#undef hash_ip_pf_test +#undef hash_ip_pf_add +#undef hash_ip_pf_readd +#undef hash_ip_pf_del +#undef hash_ip_pf_map_expired +#undef hash_ip_pf_set_expired +#undef hash_ip_pf_head +#undef hash_ip_pf_list +#undef hash_ip_pf_resize +#undef hash_ip_pf +#undef hash_ip_pf_kadt +#undef hash_ip_pf_uadt +#undef hash_ip_pf_destroy +#undef hash_ip_pf_flush +#undef hash_ip_pf_timeout_gc +#undef hash_ip_pf_gc_init +#undef ip_pf_hash +#undef ip_pf_cmp +#undef ip_pf_null +#undef ip_pf_cpy +#undef ip_pf_zero_out +#undef ip_pf_elem +#undef ip_pf_elem_timeout +#undef ip_pf_get_elem_timeout -- cgit v1.2.3