From ff27f614770695dd388eeb7b690c45208040ede5 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Thu, 24 Feb 2011 00:01:15 +0100 Subject: [PATCH 1/4] ipset: rename ipset-5 directory to ipset-6 --- INSTALL | 2 +- configure.ac | 2 +- extensions/Kbuild | 2 +- extensions/Mbuild | 2 +- extensions/{ipset-5 => ipset-6}/.gitignore | 0 extensions/{ipset-5 => ipset-6}/Kbuild | 0 extensions/{ipset-5 => ipset-6}/Makefile.am | 0 extensions/{ipset-5 => ipset-6}/Mbuild | 0 extensions/{ipset-5 => ipset-6}/VERSION.txt | 0 extensions/{ipset-5 => ipset-6}/include/libipset/data.h | 0 extensions/{ipset-5 => ipset-6}/include/libipset/debug.h | 0 extensions/{ipset-5 => ipset-6}/include/libipset/errcode.h | 0 extensions/{ipset-5 => ipset-6}/include/libipset/icmp.h | 0 extensions/{ipset-5 => ipset-6}/include/libipset/icmpv6.h | 0 extensions/{ipset-5 => ipset-6}/include/libipset/linux_ip_set.h | 0 .../{ipset-5 => ipset-6}/include/libipset/linux_ip_set_bitmap.h | 0 .../{ipset-5 => ipset-6}/include/libipset/linux_ip_set_hash.h | 0 .../{ipset-5 => ipset-6}/include/libipset/linux_ip_set_list.h | 0 extensions/{ipset-5 => ipset-6}/include/libipset/mnl.h | 0 extensions/{ipset-5 => ipset-6}/include/libipset/nf_inet_addr.h | 0 extensions/{ipset-5 => ipset-6}/include/libipset/parse.h | 0 extensions/{ipset-5 => ipset-6}/include/libipset/pfxlen.h | 0 extensions/{ipset-5 => ipset-6}/include/libipset/print.h | 0 extensions/{ipset-5 => ipset-6}/include/libipset/session.h | 0 extensions/{ipset-5 => ipset-6}/include/libipset/transport.h | 0 extensions/{ipset-5 => ipset-6}/include/libipset/types.h | 0 extensions/{ipset-5 => ipset-6}/include/libipset/ui.h | 0 extensions/{ipset-5 => ipset-6}/include/libipset/utils.h | 0 extensions/{ipset-5 => ipset-6}/ip_set.h | 0 extensions/{ipset-5 => ipset-6}/ip_set_ahash.h | 0 extensions/{ipset-5 => ipset-6}/ip_set_bitmap.h | 0 extensions/{ipset-5 => ipset-6}/ip_set_bitmap_ip.c | 0 extensions/{ipset-5 => ipset-6}/ip_set_bitmap_ipmac.c | 0 extensions/{ipset-5 => ipset-6}/ip_set_bitmap_port.c | 0 extensions/{ipset-5 => ipset-6}/ip_set_chash.h | 0 extensions/{ipset-5 => ipset-6}/ip_set_core.c | 0 extensions/{ipset-5 => ipset-6}/ip_set_getport.c | 0 extensions/{ipset-5 => ipset-6}/ip_set_getport.h | 0 extensions/{ipset-5 => ipset-6}/ip_set_hash.h | 0 extensions/{ipset-5 => ipset-6}/ip_set_hash_ip.c | 0 extensions/{ipset-5 => ipset-6}/ip_set_hash_ipport.c | 0 extensions/{ipset-5 => ipset-6}/ip_set_hash_ipportip.c | 0 extensions/{ipset-5 => ipset-6}/ip_set_hash_ipportnet.c | 0 extensions/{ipset-5 => ipset-6}/ip_set_hash_net.c | 0 extensions/{ipset-5 => ipset-6}/ip_set_hash_netport.c | 0 extensions/{ipset-5 => ipset-6}/ip_set_list.h | 0 extensions/{ipset-5 => ipset-6}/ip_set_list_set.c | 0 extensions/{ipset-5 => ipset-6}/ip_set_timeout.h | 0 extensions/{ipset-5 => ipset-6}/ipset.8 | 0 extensions/{ipset-5 => ipset-6}/jhash.h | 0 extensions/{ipset-5 => ipset-6}/libipset/data.c | 0 extensions/{ipset-5 => ipset-6}/libipset/icmp.c | 0 extensions/{ipset-5 => ipset-6}/libipset/icmpv6.c | 0 extensions/{ipset-5 => ipset-6}/libipset/mnl.c | 0 extensions/{ipset-5 => ipset-6}/libipset/parse.c | 0 extensions/{ipset-5 => ipset-6}/libipset/print.c | 0 extensions/{ipset-5 => ipset-6}/libipset/session.c | 0 extensions/{ipset-5 => ipset-6}/libipset/types.c | 0 extensions/{ipset-5 => ipset-6}/pfxlen.c | 0 extensions/{ipset-5 => ipset-6}/pfxlen.h | 0 extensions/{ipset-5 => ipset-6}/slist.h | 0 extensions/{ipset-5 => ipset-6}/src/errcode.c | 0 extensions/{ipset-5 => ipset-6}/src/ipset.c | 0 extensions/{ipset-5 => ipset-6}/src/ipset_bitmap_ip.c | 0 extensions/{ipset-5 => ipset-6}/src/ipset_bitmap_ipmac.c | 0 extensions/{ipset-5 => ipset-6}/src/ipset_bitmap_port.c | 0 extensions/{ipset-5 => ipset-6}/src/ipset_hash_ip.c | 0 extensions/{ipset-5 => ipset-6}/src/ipset_hash_ipport.c | 0 extensions/{ipset-5 => ipset-6}/src/ipset_hash_ipportip.c | 0 extensions/{ipset-5 => ipset-6}/src/ipset_hash_ipportnet.c | 0 extensions/{ipset-5 => ipset-6}/src/ipset_hash_net.c | 0 extensions/{ipset-5 => ipset-6}/src/ipset_hash_netport.c | 0 extensions/{ipset-5 => ipset-6}/src/ipset_list_set.c | 0 extensions/{ipset-5 => ipset-6}/src/ui.c | 0 extensions/{ipset-5 => ipset-6}/xt_set.c | 0 extensions/{ipset-5 => ipset-6}/xt_set.h | 0 mconfig | 2 +- 77 files changed, 5 insertions(+), 5 deletions(-) rename extensions/{ipset-5 => ipset-6}/.gitignore (100%) rename extensions/{ipset-5 => ipset-6}/Kbuild (100%) rename extensions/{ipset-5 => ipset-6}/Makefile.am (100%) rename extensions/{ipset-5 => ipset-6}/Mbuild (100%) rename extensions/{ipset-5 => ipset-6}/VERSION.txt (100%) rename extensions/{ipset-5 => ipset-6}/include/libipset/data.h (100%) rename extensions/{ipset-5 => ipset-6}/include/libipset/debug.h (100%) rename extensions/{ipset-5 => ipset-6}/include/libipset/errcode.h (100%) rename extensions/{ipset-5 => ipset-6}/include/libipset/icmp.h (100%) rename extensions/{ipset-5 => ipset-6}/include/libipset/icmpv6.h (100%) rename extensions/{ipset-5 => ipset-6}/include/libipset/linux_ip_set.h (100%) rename extensions/{ipset-5 => ipset-6}/include/libipset/linux_ip_set_bitmap.h (100%) rename extensions/{ipset-5 => ipset-6}/include/libipset/linux_ip_set_hash.h (100%) rename extensions/{ipset-5 => ipset-6}/include/libipset/linux_ip_set_list.h (100%) rename extensions/{ipset-5 => ipset-6}/include/libipset/mnl.h (100%) rename extensions/{ipset-5 => ipset-6}/include/libipset/nf_inet_addr.h (100%) rename extensions/{ipset-5 => ipset-6}/include/libipset/parse.h (100%) rename extensions/{ipset-5 => ipset-6}/include/libipset/pfxlen.h (100%) rename extensions/{ipset-5 => ipset-6}/include/libipset/print.h (100%) rename extensions/{ipset-5 => ipset-6}/include/libipset/session.h (100%) rename extensions/{ipset-5 => ipset-6}/include/libipset/transport.h (100%) rename extensions/{ipset-5 => ipset-6}/include/libipset/types.h (100%) rename extensions/{ipset-5 => ipset-6}/include/libipset/ui.h (100%) rename extensions/{ipset-5 => ipset-6}/include/libipset/utils.h (100%) rename extensions/{ipset-5 => ipset-6}/ip_set.h (100%) rename extensions/{ipset-5 => ipset-6}/ip_set_ahash.h (100%) rename extensions/{ipset-5 => ipset-6}/ip_set_bitmap.h (100%) rename extensions/{ipset-5 => ipset-6}/ip_set_bitmap_ip.c (100%) rename extensions/{ipset-5 => ipset-6}/ip_set_bitmap_ipmac.c (100%) rename extensions/{ipset-5 => ipset-6}/ip_set_bitmap_port.c (100%) rename extensions/{ipset-5 => ipset-6}/ip_set_chash.h (100%) rename extensions/{ipset-5 => ipset-6}/ip_set_core.c (100%) rename extensions/{ipset-5 => ipset-6}/ip_set_getport.c (100%) rename extensions/{ipset-5 => ipset-6}/ip_set_getport.h (100%) rename extensions/{ipset-5 => ipset-6}/ip_set_hash.h (100%) rename extensions/{ipset-5 => ipset-6}/ip_set_hash_ip.c (100%) rename extensions/{ipset-5 => ipset-6}/ip_set_hash_ipport.c (100%) rename extensions/{ipset-5 => ipset-6}/ip_set_hash_ipportip.c (100%) rename extensions/{ipset-5 => ipset-6}/ip_set_hash_ipportnet.c (100%) rename extensions/{ipset-5 => ipset-6}/ip_set_hash_net.c (100%) rename extensions/{ipset-5 => ipset-6}/ip_set_hash_netport.c (100%) rename extensions/{ipset-5 => ipset-6}/ip_set_list.h (100%) rename extensions/{ipset-5 => ipset-6}/ip_set_list_set.c (100%) rename extensions/{ipset-5 => ipset-6}/ip_set_timeout.h (100%) rename extensions/{ipset-5 => ipset-6}/ipset.8 (100%) rename extensions/{ipset-5 => ipset-6}/jhash.h (100%) rename extensions/{ipset-5 => ipset-6}/libipset/data.c (100%) rename extensions/{ipset-5 => ipset-6}/libipset/icmp.c (100%) rename extensions/{ipset-5 => ipset-6}/libipset/icmpv6.c (100%) rename extensions/{ipset-5 => ipset-6}/libipset/mnl.c (100%) rename extensions/{ipset-5 => ipset-6}/libipset/parse.c (100%) rename extensions/{ipset-5 => ipset-6}/libipset/print.c (100%) rename extensions/{ipset-5 => ipset-6}/libipset/session.c (100%) rename extensions/{ipset-5 => ipset-6}/libipset/types.c (100%) rename extensions/{ipset-5 => ipset-6}/pfxlen.c (100%) rename extensions/{ipset-5 => ipset-6}/pfxlen.h (100%) rename extensions/{ipset-5 => ipset-6}/slist.h (100%) rename extensions/{ipset-5 => ipset-6}/src/errcode.c (100%) rename extensions/{ipset-5 => ipset-6}/src/ipset.c (100%) rename extensions/{ipset-5 => ipset-6}/src/ipset_bitmap_ip.c (100%) rename extensions/{ipset-5 => ipset-6}/src/ipset_bitmap_ipmac.c (100%) rename extensions/{ipset-5 => ipset-6}/src/ipset_bitmap_port.c (100%) rename extensions/{ipset-5 => ipset-6}/src/ipset_hash_ip.c (100%) rename extensions/{ipset-5 => ipset-6}/src/ipset_hash_ipport.c (100%) rename extensions/{ipset-5 => ipset-6}/src/ipset_hash_ipportip.c (100%) rename extensions/{ipset-5 => ipset-6}/src/ipset_hash_ipportnet.c (100%) rename extensions/{ipset-5 => ipset-6}/src/ipset_hash_net.c (100%) rename extensions/{ipset-5 => ipset-6}/src/ipset_hash_netport.c (100%) rename extensions/{ipset-5 => ipset-6}/src/ipset_list_set.c (100%) rename extensions/{ipset-5 => ipset-6}/src/ui.c (100%) rename extensions/{ipset-5 => ipset-6}/xt_set.c (100%) rename extensions/{ipset-5 => ipset-6}/xt_set.h (100%) diff --git a/INSTALL b/INSTALL index a1e3a77..ed05993 100644 --- a/INSTALL +++ b/INSTALL @@ -28,7 +28,7 @@ Extra notes: * requires that no vendor backports interfere -For ipset-5 you need: +For ipset-6 you need: * libmnl diff --git a/configure.ac b/configure.ac index 80006a6..9709815 100644 --- a/configure.ac +++ b/configure.ac @@ -89,6 +89,6 @@ AC_SUBST([kbuilddir]) AC_SUBST([xtlibdir]) AC_CONFIG_FILES([Makefile Makefile.iptrules Makefile.mans geoip/Makefile extensions/Makefile extensions/ACCOUNT/Makefile - extensions/ipset-4/Makefile extensions/ipset-5/Makefile + extensions/ipset-4/Makefile extensions/ipset-6/Makefile extensions/pknock/Makefile]) AC_OUTPUT diff --git a/extensions/Kbuild b/extensions/Kbuild index 6274627..7414fe6 100644 --- a/extensions/Kbuild +++ b/extensions/Kbuild @@ -28,7 +28,7 @@ obj-${build_geoip} += xt_geoip.o obj-${build_iface} += xt_iface.o obj-${build_ipp2p} += xt_ipp2p.o obj-${build_ipset4} += ipset-4/ -obj-${build_ipset5} += ipset-5/ +obj-${build_ipset6} += ipset-6/ obj-${build_ipv4options} += xt_ipv4options.o obj-${build_length2} += xt_length2.o obj-${build_lscan} += xt_lscan.o diff --git a/extensions/Mbuild b/extensions/Mbuild index c0e7ca3..65be562 100644 --- a/extensions/Mbuild +++ b/extensions/Mbuild @@ -20,7 +20,7 @@ obj-${build_geoip} += libxt_geoip.so obj-${build_iface} += libxt_iface.so obj-${build_ipp2p} += libxt_ipp2p.so obj-${build_ipset4} += ipset-4/ -obj-${build_ipset5} += ipset-5/ +obj-${build_ipset6} += ipset-6/ obj-${build_ipv4options} += libxt_ipv4options.so obj-${build_length2} += libxt_length2.so obj-${build_lscan} += libxt_lscan.so diff --git a/extensions/ipset-5/.gitignore b/extensions/ipset-6/.gitignore similarity index 100% rename from extensions/ipset-5/.gitignore rename to extensions/ipset-6/.gitignore diff --git a/extensions/ipset-5/Kbuild b/extensions/ipset-6/Kbuild similarity index 100% rename from extensions/ipset-5/Kbuild rename to extensions/ipset-6/Kbuild diff --git a/extensions/ipset-5/Makefile.am b/extensions/ipset-6/Makefile.am similarity index 100% rename from extensions/ipset-5/Makefile.am rename to extensions/ipset-6/Makefile.am diff --git a/extensions/ipset-5/Mbuild b/extensions/ipset-6/Mbuild similarity index 100% rename from extensions/ipset-5/Mbuild rename to extensions/ipset-6/Mbuild diff --git a/extensions/ipset-5/VERSION.txt b/extensions/ipset-6/VERSION.txt similarity index 100% rename from extensions/ipset-5/VERSION.txt rename to extensions/ipset-6/VERSION.txt diff --git a/extensions/ipset-5/include/libipset/data.h b/extensions/ipset-6/include/libipset/data.h similarity index 100% rename from extensions/ipset-5/include/libipset/data.h rename to extensions/ipset-6/include/libipset/data.h diff --git a/extensions/ipset-5/include/libipset/debug.h b/extensions/ipset-6/include/libipset/debug.h similarity index 100% rename from extensions/ipset-5/include/libipset/debug.h rename to extensions/ipset-6/include/libipset/debug.h diff --git a/extensions/ipset-5/include/libipset/errcode.h b/extensions/ipset-6/include/libipset/errcode.h similarity index 100% rename from extensions/ipset-5/include/libipset/errcode.h rename to extensions/ipset-6/include/libipset/errcode.h diff --git a/extensions/ipset-5/include/libipset/icmp.h b/extensions/ipset-6/include/libipset/icmp.h similarity index 100% rename from extensions/ipset-5/include/libipset/icmp.h rename to extensions/ipset-6/include/libipset/icmp.h diff --git a/extensions/ipset-5/include/libipset/icmpv6.h b/extensions/ipset-6/include/libipset/icmpv6.h similarity index 100% rename from extensions/ipset-5/include/libipset/icmpv6.h rename to extensions/ipset-6/include/libipset/icmpv6.h diff --git a/extensions/ipset-5/include/libipset/linux_ip_set.h b/extensions/ipset-6/include/libipset/linux_ip_set.h similarity index 100% rename from extensions/ipset-5/include/libipset/linux_ip_set.h rename to extensions/ipset-6/include/libipset/linux_ip_set.h diff --git a/extensions/ipset-5/include/libipset/linux_ip_set_bitmap.h b/extensions/ipset-6/include/libipset/linux_ip_set_bitmap.h similarity index 100% rename from extensions/ipset-5/include/libipset/linux_ip_set_bitmap.h rename to extensions/ipset-6/include/libipset/linux_ip_set_bitmap.h diff --git a/extensions/ipset-5/include/libipset/linux_ip_set_hash.h b/extensions/ipset-6/include/libipset/linux_ip_set_hash.h similarity index 100% rename from extensions/ipset-5/include/libipset/linux_ip_set_hash.h rename to extensions/ipset-6/include/libipset/linux_ip_set_hash.h diff --git a/extensions/ipset-5/include/libipset/linux_ip_set_list.h b/extensions/ipset-6/include/libipset/linux_ip_set_list.h similarity index 100% rename from extensions/ipset-5/include/libipset/linux_ip_set_list.h rename to extensions/ipset-6/include/libipset/linux_ip_set_list.h diff --git a/extensions/ipset-5/include/libipset/mnl.h b/extensions/ipset-6/include/libipset/mnl.h similarity index 100% rename from extensions/ipset-5/include/libipset/mnl.h rename to extensions/ipset-6/include/libipset/mnl.h diff --git a/extensions/ipset-5/include/libipset/nf_inet_addr.h b/extensions/ipset-6/include/libipset/nf_inet_addr.h similarity index 100% rename from extensions/ipset-5/include/libipset/nf_inet_addr.h rename to extensions/ipset-6/include/libipset/nf_inet_addr.h diff --git a/extensions/ipset-5/include/libipset/parse.h b/extensions/ipset-6/include/libipset/parse.h similarity index 100% rename from extensions/ipset-5/include/libipset/parse.h rename to extensions/ipset-6/include/libipset/parse.h diff --git a/extensions/ipset-5/include/libipset/pfxlen.h b/extensions/ipset-6/include/libipset/pfxlen.h similarity index 100% rename from extensions/ipset-5/include/libipset/pfxlen.h rename to extensions/ipset-6/include/libipset/pfxlen.h diff --git a/extensions/ipset-5/include/libipset/print.h b/extensions/ipset-6/include/libipset/print.h similarity index 100% rename from extensions/ipset-5/include/libipset/print.h rename to extensions/ipset-6/include/libipset/print.h diff --git a/extensions/ipset-5/include/libipset/session.h b/extensions/ipset-6/include/libipset/session.h similarity index 100% rename from extensions/ipset-5/include/libipset/session.h rename to extensions/ipset-6/include/libipset/session.h diff --git a/extensions/ipset-5/include/libipset/transport.h b/extensions/ipset-6/include/libipset/transport.h similarity index 100% rename from extensions/ipset-5/include/libipset/transport.h rename to extensions/ipset-6/include/libipset/transport.h diff --git a/extensions/ipset-5/include/libipset/types.h b/extensions/ipset-6/include/libipset/types.h similarity index 100% rename from extensions/ipset-5/include/libipset/types.h rename to extensions/ipset-6/include/libipset/types.h diff --git a/extensions/ipset-5/include/libipset/ui.h b/extensions/ipset-6/include/libipset/ui.h similarity index 100% rename from extensions/ipset-5/include/libipset/ui.h rename to extensions/ipset-6/include/libipset/ui.h diff --git a/extensions/ipset-5/include/libipset/utils.h b/extensions/ipset-6/include/libipset/utils.h similarity index 100% rename from extensions/ipset-5/include/libipset/utils.h rename to extensions/ipset-6/include/libipset/utils.h diff --git a/extensions/ipset-5/ip_set.h b/extensions/ipset-6/ip_set.h similarity index 100% rename from extensions/ipset-5/ip_set.h rename to extensions/ipset-6/ip_set.h diff --git a/extensions/ipset-5/ip_set_ahash.h b/extensions/ipset-6/ip_set_ahash.h similarity index 100% rename from extensions/ipset-5/ip_set_ahash.h rename to extensions/ipset-6/ip_set_ahash.h diff --git a/extensions/ipset-5/ip_set_bitmap.h b/extensions/ipset-6/ip_set_bitmap.h similarity index 100% rename from extensions/ipset-5/ip_set_bitmap.h rename to extensions/ipset-6/ip_set_bitmap.h diff --git a/extensions/ipset-5/ip_set_bitmap_ip.c b/extensions/ipset-6/ip_set_bitmap_ip.c similarity index 100% rename from extensions/ipset-5/ip_set_bitmap_ip.c rename to extensions/ipset-6/ip_set_bitmap_ip.c diff --git a/extensions/ipset-5/ip_set_bitmap_ipmac.c b/extensions/ipset-6/ip_set_bitmap_ipmac.c similarity index 100% rename from extensions/ipset-5/ip_set_bitmap_ipmac.c rename to extensions/ipset-6/ip_set_bitmap_ipmac.c diff --git a/extensions/ipset-5/ip_set_bitmap_port.c b/extensions/ipset-6/ip_set_bitmap_port.c similarity index 100% rename from extensions/ipset-5/ip_set_bitmap_port.c rename to extensions/ipset-6/ip_set_bitmap_port.c diff --git a/extensions/ipset-5/ip_set_chash.h b/extensions/ipset-6/ip_set_chash.h similarity index 100% rename from extensions/ipset-5/ip_set_chash.h rename to extensions/ipset-6/ip_set_chash.h diff --git a/extensions/ipset-5/ip_set_core.c b/extensions/ipset-6/ip_set_core.c similarity index 100% rename from extensions/ipset-5/ip_set_core.c rename to extensions/ipset-6/ip_set_core.c diff --git a/extensions/ipset-5/ip_set_getport.c b/extensions/ipset-6/ip_set_getport.c similarity index 100% rename from extensions/ipset-5/ip_set_getport.c rename to extensions/ipset-6/ip_set_getport.c diff --git a/extensions/ipset-5/ip_set_getport.h b/extensions/ipset-6/ip_set_getport.h similarity index 100% rename from extensions/ipset-5/ip_set_getport.h rename to extensions/ipset-6/ip_set_getport.h diff --git a/extensions/ipset-5/ip_set_hash.h b/extensions/ipset-6/ip_set_hash.h similarity index 100% rename from extensions/ipset-5/ip_set_hash.h rename to extensions/ipset-6/ip_set_hash.h diff --git a/extensions/ipset-5/ip_set_hash_ip.c b/extensions/ipset-6/ip_set_hash_ip.c similarity index 100% rename from extensions/ipset-5/ip_set_hash_ip.c rename to extensions/ipset-6/ip_set_hash_ip.c diff --git a/extensions/ipset-5/ip_set_hash_ipport.c b/extensions/ipset-6/ip_set_hash_ipport.c similarity index 100% rename from extensions/ipset-5/ip_set_hash_ipport.c rename to extensions/ipset-6/ip_set_hash_ipport.c diff --git a/extensions/ipset-5/ip_set_hash_ipportip.c b/extensions/ipset-6/ip_set_hash_ipportip.c similarity index 100% rename from extensions/ipset-5/ip_set_hash_ipportip.c rename to extensions/ipset-6/ip_set_hash_ipportip.c diff --git a/extensions/ipset-5/ip_set_hash_ipportnet.c b/extensions/ipset-6/ip_set_hash_ipportnet.c similarity index 100% rename from extensions/ipset-5/ip_set_hash_ipportnet.c rename to extensions/ipset-6/ip_set_hash_ipportnet.c diff --git a/extensions/ipset-5/ip_set_hash_net.c b/extensions/ipset-6/ip_set_hash_net.c similarity index 100% rename from extensions/ipset-5/ip_set_hash_net.c rename to extensions/ipset-6/ip_set_hash_net.c diff --git a/extensions/ipset-5/ip_set_hash_netport.c b/extensions/ipset-6/ip_set_hash_netport.c similarity index 100% rename from extensions/ipset-5/ip_set_hash_netport.c rename to extensions/ipset-6/ip_set_hash_netport.c diff --git a/extensions/ipset-5/ip_set_list.h b/extensions/ipset-6/ip_set_list.h similarity index 100% rename from extensions/ipset-5/ip_set_list.h rename to extensions/ipset-6/ip_set_list.h diff --git a/extensions/ipset-5/ip_set_list_set.c b/extensions/ipset-6/ip_set_list_set.c similarity index 100% rename from extensions/ipset-5/ip_set_list_set.c rename to extensions/ipset-6/ip_set_list_set.c diff --git a/extensions/ipset-5/ip_set_timeout.h b/extensions/ipset-6/ip_set_timeout.h similarity index 100% rename from extensions/ipset-5/ip_set_timeout.h rename to extensions/ipset-6/ip_set_timeout.h diff --git a/extensions/ipset-5/ipset.8 b/extensions/ipset-6/ipset.8 similarity index 100% rename from extensions/ipset-5/ipset.8 rename to extensions/ipset-6/ipset.8 diff --git a/extensions/ipset-5/jhash.h b/extensions/ipset-6/jhash.h similarity index 100% rename from extensions/ipset-5/jhash.h rename to extensions/ipset-6/jhash.h diff --git a/extensions/ipset-5/libipset/data.c b/extensions/ipset-6/libipset/data.c similarity index 100% rename from extensions/ipset-5/libipset/data.c rename to extensions/ipset-6/libipset/data.c diff --git a/extensions/ipset-5/libipset/icmp.c b/extensions/ipset-6/libipset/icmp.c similarity index 100% rename from extensions/ipset-5/libipset/icmp.c rename to extensions/ipset-6/libipset/icmp.c diff --git a/extensions/ipset-5/libipset/icmpv6.c b/extensions/ipset-6/libipset/icmpv6.c similarity index 100% rename from extensions/ipset-5/libipset/icmpv6.c rename to extensions/ipset-6/libipset/icmpv6.c diff --git a/extensions/ipset-5/libipset/mnl.c b/extensions/ipset-6/libipset/mnl.c similarity index 100% rename from extensions/ipset-5/libipset/mnl.c rename to extensions/ipset-6/libipset/mnl.c diff --git a/extensions/ipset-5/libipset/parse.c b/extensions/ipset-6/libipset/parse.c similarity index 100% rename from extensions/ipset-5/libipset/parse.c rename to extensions/ipset-6/libipset/parse.c diff --git a/extensions/ipset-5/libipset/print.c b/extensions/ipset-6/libipset/print.c similarity index 100% rename from extensions/ipset-5/libipset/print.c rename to extensions/ipset-6/libipset/print.c diff --git a/extensions/ipset-5/libipset/session.c b/extensions/ipset-6/libipset/session.c similarity index 100% rename from extensions/ipset-5/libipset/session.c rename to extensions/ipset-6/libipset/session.c diff --git a/extensions/ipset-5/libipset/types.c b/extensions/ipset-6/libipset/types.c similarity index 100% rename from extensions/ipset-5/libipset/types.c rename to extensions/ipset-6/libipset/types.c diff --git a/extensions/ipset-5/pfxlen.c b/extensions/ipset-6/pfxlen.c similarity index 100% rename from extensions/ipset-5/pfxlen.c rename to extensions/ipset-6/pfxlen.c diff --git a/extensions/ipset-5/pfxlen.h b/extensions/ipset-6/pfxlen.h similarity index 100% rename from extensions/ipset-5/pfxlen.h rename to extensions/ipset-6/pfxlen.h diff --git a/extensions/ipset-5/slist.h b/extensions/ipset-6/slist.h similarity index 100% rename from extensions/ipset-5/slist.h rename to extensions/ipset-6/slist.h diff --git a/extensions/ipset-5/src/errcode.c b/extensions/ipset-6/src/errcode.c similarity index 100% rename from extensions/ipset-5/src/errcode.c rename to extensions/ipset-6/src/errcode.c diff --git a/extensions/ipset-5/src/ipset.c b/extensions/ipset-6/src/ipset.c similarity index 100% rename from extensions/ipset-5/src/ipset.c rename to extensions/ipset-6/src/ipset.c diff --git a/extensions/ipset-5/src/ipset_bitmap_ip.c b/extensions/ipset-6/src/ipset_bitmap_ip.c similarity index 100% rename from extensions/ipset-5/src/ipset_bitmap_ip.c rename to extensions/ipset-6/src/ipset_bitmap_ip.c diff --git a/extensions/ipset-5/src/ipset_bitmap_ipmac.c b/extensions/ipset-6/src/ipset_bitmap_ipmac.c similarity index 100% rename from extensions/ipset-5/src/ipset_bitmap_ipmac.c rename to extensions/ipset-6/src/ipset_bitmap_ipmac.c diff --git a/extensions/ipset-5/src/ipset_bitmap_port.c b/extensions/ipset-6/src/ipset_bitmap_port.c similarity index 100% rename from extensions/ipset-5/src/ipset_bitmap_port.c rename to extensions/ipset-6/src/ipset_bitmap_port.c diff --git a/extensions/ipset-5/src/ipset_hash_ip.c b/extensions/ipset-6/src/ipset_hash_ip.c similarity index 100% rename from extensions/ipset-5/src/ipset_hash_ip.c rename to extensions/ipset-6/src/ipset_hash_ip.c diff --git a/extensions/ipset-5/src/ipset_hash_ipport.c b/extensions/ipset-6/src/ipset_hash_ipport.c similarity index 100% rename from extensions/ipset-5/src/ipset_hash_ipport.c rename to extensions/ipset-6/src/ipset_hash_ipport.c diff --git a/extensions/ipset-5/src/ipset_hash_ipportip.c b/extensions/ipset-6/src/ipset_hash_ipportip.c similarity index 100% rename from extensions/ipset-5/src/ipset_hash_ipportip.c rename to extensions/ipset-6/src/ipset_hash_ipportip.c diff --git a/extensions/ipset-5/src/ipset_hash_ipportnet.c b/extensions/ipset-6/src/ipset_hash_ipportnet.c similarity index 100% rename from extensions/ipset-5/src/ipset_hash_ipportnet.c rename to extensions/ipset-6/src/ipset_hash_ipportnet.c diff --git a/extensions/ipset-5/src/ipset_hash_net.c b/extensions/ipset-6/src/ipset_hash_net.c similarity index 100% rename from extensions/ipset-5/src/ipset_hash_net.c rename to extensions/ipset-6/src/ipset_hash_net.c diff --git a/extensions/ipset-5/src/ipset_hash_netport.c b/extensions/ipset-6/src/ipset_hash_netport.c similarity index 100% rename from extensions/ipset-5/src/ipset_hash_netport.c rename to extensions/ipset-6/src/ipset_hash_netport.c diff --git a/extensions/ipset-5/src/ipset_list_set.c b/extensions/ipset-6/src/ipset_list_set.c similarity index 100% rename from extensions/ipset-5/src/ipset_list_set.c rename to extensions/ipset-6/src/ipset_list_set.c diff --git a/extensions/ipset-5/src/ui.c b/extensions/ipset-6/src/ui.c similarity index 100% rename from extensions/ipset-5/src/ui.c rename to extensions/ipset-6/src/ui.c diff --git a/extensions/ipset-5/xt_set.c b/extensions/ipset-6/xt_set.c similarity index 100% rename from extensions/ipset-5/xt_set.c rename to extensions/ipset-6/xt_set.c diff --git a/extensions/ipset-5/xt_set.h b/extensions/ipset-6/xt_set.h similarity index 100% rename from extensions/ipset-5/xt_set.h rename to extensions/ipset-6/xt_set.h diff --git a/mconfig b/mconfig index 0d33d7d..03c8719 100644 --- a/mconfig +++ b/mconfig @@ -21,7 +21,7 @@ build_gradm=m build_iface=m build_ipp2p=m build_ipset4=m -build_ipset5= +build_ipset6= build_ipv4options=m build_length2=m build_lscan=m From 18043f3e3afc8ec8a9a33db554d5352a672679a0 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Thu, 24 Feb 2011 00:40:23 +0100 Subject: [PATCH 2/4] ipset: update to 6.0 --- doc/changelog.txt | 14 + extensions/ipset-6/README | 88 +++ .../ipset-6/include/libipset/linux_ip_set.h | 8 +- extensions/ipset-6/include/libipset/parse.h | 5 +- extensions/ipset-6/include/libipset/types.h | 2 +- extensions/ipset-6/ip_set.h | 17 +- extensions/ipset-6/ip_set_ahash.h | 20 +- extensions/ipset-6/ip_set_bitmap_ip.c | 587 +++++++----------- extensions/ipset-6/ip_set_bitmap_ipmac.c | 64 +- extensions/ipset-6/ip_set_bitmap_port.c | 572 +++++++---------- extensions/ipset-6/ip_set_core.c | 168 +++-- extensions/ipset-6/ip_set_getport.c | 17 +- extensions/ipset-6/ip_set_getport.h | 10 + extensions/ipset-6/ip_set_hash_ip.c | 64 +- extensions/ipset-6/ip_set_hash_ipport.c | 71 +-- extensions/ipset-6/ip_set_hash_ipportip.c | 72 +-- extensions/ipset-6/ip_set_hash_ipportnet.c | 74 +-- extensions/ipset-6/ip_set_hash_net.c | 54 +- extensions/ipset-6/ip_set_hash_netport.c | 65 +- extensions/ipset-6/ip_set_list_set.c | 54 +- extensions/ipset-6/libipset/mnl.c | 7 +- extensions/ipset-6/libipset/parse.c | 11 +- extensions/ipset-6/libipset/print.c | 7 +- extensions/ipset-6/libipset/types.c | 17 +- extensions/ipset-6/src/errcode.c | 8 +- extensions/ipset-6/src/ipset.c | 151 +++-- extensions/ipset-6/src/ui.c | 14 +- extensions/ipset-6/xt_set.c | 44 +- extensions/ipset-6/xt_set.h | 1 + mconfig | 29 +- 30 files changed, 1016 insertions(+), 1299 deletions(-) create mode 100644 extensions/ipset-6/README diff --git a/doc/changelog.txt b/doc/changelog.txt index 3a21fb4..922054b 100644 --- a/doc/changelog.txt +++ b/doc/changelog.txt @@ -1,6 +1,20 @@ HEAD ==== +Enhancements: +- update to ipset 6.0 + * allow "new" as a commad alias to "create" + * ipset: improve command argument parsing + * ipset: avoid the unnecessary argv[] loop + * ipset: pass ipset_arg argument pointer + * separate ipset errnos completely from system ones and bump protocol version + * resolving IP addresses did not work at listing/saving sets, fixed + * ipset: fix spelling error + * ipset: fix the Netlink sequence number + * ipset: turn Set name[] into a const pointer + * check ICMP and ICMPv6 with the set match and target in the testsuite + * avoid possible syntax clashing at saving hostnames + * fix linking with CONFIG_IPV6=n v1.33 (2011-02-02) diff --git a/extensions/ipset-6/README b/extensions/ipset-6/README new file mode 100644 index 0000000..a7ef16c --- /dev/null +++ b/extensions/ipset-6/README @@ -0,0 +1,88 @@ +This is the ipset source tree. Follow the next steps to install ipset. +If you upgrade from an earlier 5.x release, please read the UPGRADE +instructions too. + +0. You need the source tree of your kernel (version >= 2.6.34) + and it have to be configured with ip6tables support enabled, + modules compiled. Please apply the netlink.patch against your kernel + tree, which adds the new subsystem identifier for ipset. + + Recompile and install the patched kernel and its modules. Please note, + you have to run the patched kernel for ipset to work. + + The ipset source code depends on the libmnl library so the library + must be installed. You can download the libmnl library from + + git://git.netfilter.org/libmnl.git + +1. Initialize the compiling environment for ipset. The packages automake, + autoconf and libtool are required. + + % ./autogen.sh + +2. Run `./configure` and then compile the ipset binary and the kernel + modules. + + Configure parameters can be used to to override the default path + to the kernel source tree (/lib/modules/`uname -r`/build), + the maximum number of sets (256), the default hash sizes (1024). + See `./configure --help`. + + % ./configure + % make + % make modules + +3. Install the binary and the kernel modules + + # make install + # make modules_install + + After installing the modules, you can run the testsuite as well. + Please note, several assumptions must be met for the testsuite: + + - no sets defined + - iptables/ip6tables rules are not set up + - the destination for kernel logs is /var/log/kern.log + - the networks 10.255.255.0/24 and 1002:1002:1002:1002::/64 + are not in use + - sendip utility is installed + + # make tests + +4. Cleanup the source tree + + % make clean + % make modules_clean + +That's it! + +Read the ipset(8) and iptables(8), ip6tables(8) manpages on how to use +ipset and its match and target from iptables. + +Compatibilities and incompatibilities: + +- The ipset 6.x userspace utility contains a backward compatibility + interface to support the commandline syntax of ipset 4.x. + The commandline syntax of ipset 6.x is fully compatible with 5.x. +- The ipset 6.x userspace utility can't talk to the kernel part of ipset 5.x + or 4.x. +- The ipset 6.x kernel part can't talk to the userspace utility from + ipset 5.x or 4.x. +- The ipset 6.x kernel part can work together with the set match and SET + target from iptables 1.4.7 and below, however if you need the IPv6 support + from ipset 6.x, then you have to use iptables 1.4.8 or above. + +The ipset 6.x can interpret the commandline syntax of ipset 4.x, however +some internal changes mean different behaviour: + +- The "--matchunset" flag for the macipmap type is ignored and not used + anymore. +- The "--probes" and "--resize" parameters of the hash types are ignored + and not used anymore. +- The "--from", "--to" and "--network" parameters of the ipporthash, + ipportiphash and ipportnethash types are ignored and not used anymore. +- The hash types are not resized when new entries are added by the SET + target. If you use a set together with the SET target, create it with + the proper size because it won't be resized automatically. +- The iptree, iptreemap types are not implemented in ipset 6.x. The types + are automatically substituted with the hash:ip type. diff --git a/extensions/ipset-6/include/libipset/linux_ip_set.h b/extensions/ipset-6/include/libipset/linux_ip_set.h index 1fb7ea2..d4b6308 100644 --- a/extensions/ipset-6/include/libipset/linux_ip_set.h +++ b/extensions/ipset-6/include/libipset/linux_ip_set.h @@ -4,7 +4,7 @@ /* Copyright (C) 2000-2002 Joakim Axelsson * Patrick Schaaf * Martin Josefsson - * Copyright (C) 2003-2010 Jozsef Kadlecsik + * Copyright (C) 2003-2011 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 @@ -12,7 +12,7 @@ */ /* The protocol version */ -#define IPSET_PROTOCOL 5 +#define IPSET_PROTOCOL 60 /* The max length of strings including NUL: set and type identifiers */ #define IPSET_MAXNAMELEN 32 @@ -118,7 +118,7 @@ enum { /* Error codes */ enum ipset_errno { - IPSET_ERR_PRIVATE = 128, + IPSET_ERR_PRIVATE = 4096, IPSET_ERR_PROTOCOL, IPSET_ERR_FIND_TYPE, IPSET_ERR_MAX_SETS, @@ -135,7 +135,7 @@ enum ipset_errno { IPSET_ERR_IPADDR_IPV6, /* Type specific error codes */ - IPSET_ERR_TYPE_SPECIFIC = 160, + IPSET_ERR_TYPE_SPECIFIC = 4352, }; /* Flags at command level */ diff --git a/extensions/ipset-6/include/libipset/parse.h b/extensions/ipset-6/include/libipset/parse.h index e87a60d..760df49 100644 --- a/extensions/ipset-6/include/libipset/parse.h +++ b/extensions/ipset-6/include/libipset/parse.h @@ -17,6 +17,7 @@ #define IPSET_PROTO_SEPARATOR ":" struct ipset_session; +struct ipset_arg; typedef int (*ipset_parsefn)(struct ipset_session *s, enum ipset_opt opt, const char *str); @@ -84,8 +85,8 @@ extern int ipset_parse_ignored(struct ipset_session *session, extern int ipset_parse_elem(struct ipset_session *session, enum ipset_opt opt, const char *str); extern int ipset_call_parser(struct ipset_session *session, - ipset_parsefn parse, const char *optstr, - enum ipset_opt optional, const char *str); + const struct ipset_arg *arg, + const char *str); /* Compatibility parser functions */ extern int ipset_parse_iptimeout(struct ipset_session *session, diff --git a/extensions/ipset-6/include/libipset/types.h b/extensions/ipset-6/include/libipset/types.h index f9c8f2d..d8973db 100644 --- a/extensions/ipset-6/include/libipset/types.h +++ b/extensions/ipset-6/include/libipset/types.h @@ -70,7 +70,7 @@ struct ipset_elem { * but for the readability the full list is supported. */ struct ipset_type { - char name[IPSET_MAXNAMELEN]; /* type name */ + const char *name; uint8_t revision; /* revision number */ uint8_t family; /* supported family */ uint8_t dimension; /* elem dimension */ diff --git a/extensions/ipset-6/ip_set.h b/extensions/ipset-6/ip_set.h index 9d4b961..ec1438f 100644 --- a/extensions/ipset-6/ip_set.h +++ b/extensions/ipset-6/ip_set.h @@ -14,7 +14,7 @@ #include /* The protocol version */ -#define IPSET_PROTOCOL 5 +#define IPSET_PROTOCOL 60 /* The max length of strings including NUL: set and type identifiers */ #define IPSET_MAXNAMELEN 32 @@ -120,7 +120,7 @@ enum { /* Error codes */ enum ipset_errno { - IPSET_ERR_PRIVATE = 128, + IPSET_ERR_PRIVATE = 4096, IPSET_ERR_PROTOCOL, IPSET_ERR_FIND_TYPE, IPSET_ERR_MAX_SETS, @@ -137,7 +137,7 @@ enum ipset_errno { IPSET_ERR_IPADDR_IPV6, /* Type specific error codes */ - IPSET_ERR_TYPE_SPECIFIC = 160, + IPSET_ERR_TYPE_SPECIFIC = 4352, }; /* Flags at command level */ @@ -231,7 +231,7 @@ struct ip_set_type_variant { * returns negative error code, * zero for no match/success to add/delete * positive for matching element */ - int (*uadt)(struct ip_set *set, struct nlattr *head, int len, + int (*uadt)(struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt, u32 *lineno, u32 flags); /* Low level add/del/test functions */ @@ -274,8 +274,11 @@ struct ip_set_type { u8 revision; /* Create set */ - int (*create)(struct ip_set *set, - struct nlattr *head, int len, u32 flags); + int (*create)(struct ip_set *set, struct nlattr *tb[], u32 flags); + + /* Attribute policies */ + const struct nla_policy create_policy[IPSET_ATTR_CREATE_MAX + 1]; + const struct nla_policy adt_policy[IPSET_ATTR_ADT_MAX + 1]; /* Set this to THIS_MODULE if you are a module, otherwise NULL */ struct module *me; @@ -320,7 +323,7 @@ extern int ip_set_test(ip_set_id_t id, const struct sk_buff *skb, u8 family, u8 dim, u8 flags); /* Utility functions */ -extern void * ip_set_alloc(size_t size, gfp_t gfp_mask); +extern void * ip_set_alloc(size_t size); extern void ip_set_free(void *members); extern int ip_set_get_ipaddr4(struct nlattr *nla, __be32 *ipaddr); extern int ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr); diff --git a/extensions/ipset-6/ip_set_ahash.h b/extensions/ipset-6/ip_set_ahash.h index 2f4bb3a..b6c4c2f 100644 --- a/extensions/ipset-6/ip_set_ahash.h +++ b/extensions/ipset-6/ip_set_ahash.h @@ -311,8 +311,7 @@ retry: /* In case we have plenty of memory :-) */ return -IPSET_ERR_HASH_FULL; t = ip_set_alloc(sizeof(*t) - + jhash_size(htable_bits) * sizeof(struct hbucket), - GFP_KERNEL); + + jhash_size(htable_bits) * sizeof(struct hbucket)); if (!t) return -ENOMEM; t->htable_bits = htable_bits; @@ -525,7 +524,7 @@ type_pf_head(struct ip_set *set, struct sk_buff *skb) return 0; nla_put_failure: - return -EFAULT; + return -EMSGSIZE; } /* Reply a LIST/SAVE request: dump the elements of the specified set */ @@ -545,7 +544,7 @@ type_pf_list(const struct ip_set *set, atd = ipset_nest_start(skb, IPSET_ATTR_ADT); if (!atd) - return -EFAULT; + return -EMSGSIZE; pr_debug("list hash set %s\n", set->name); for (; cb->args[2] < jhash_size(t->htable_bits); cb->args[2]++) { incomplete = skb_tail_pointer(skb); @@ -559,7 +558,7 @@ type_pf_list(const struct ip_set *set, if (!nested) { if (cb->args[2] == first) { nla_nest_cancel(skb, atd); - return -EFAULT; + return -EMSGSIZE; } else goto nla_put_failure; } @@ -581,6 +580,7 @@ nla_put_failure: pr_warning("Can't list set %s: one bucket does not fit into " "a message. Please report it!\n", set->name); cb->args[2] = 0; + return -EMSGSIZE; } return 0; } @@ -589,7 +589,7 @@ static int type_pf_kadt(struct ip_set *set, const struct sk_buff * skb, enum ipset_adt adt, u8 pf, u8 dim, u8 flags); static int -type_pf_uadt(struct ip_set *set, struct nlattr *head, int len, +type_pf_uadt(struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt, u32 *lineno, u32 flags); static const struct ip_set_type_variant type_pf_variant = { @@ -742,8 +742,7 @@ retry: /* In case we have plenty of memory :-) */ return -IPSET_ERR_HASH_FULL; t = ip_set_alloc(sizeof(*t) - + jhash_size(htable_bits) * sizeof(struct hbucket), - GFP_KERNEL); + + jhash_size(htable_bits) * sizeof(struct hbucket)); if (!t) return -ENOMEM; t->htable_bits = htable_bits; @@ -946,7 +945,7 @@ type_pf_tlist(const struct ip_set *set, atd = ipset_nest_start(skb, IPSET_ATTR_ADT); if (!atd) - return -EFAULT; + return -EMSGSIZE; for (; cb->args[2] < jhash_size(t->htable_bits); cb->args[2]++) { incomplete = skb_tail_pointer(skb); n = hbucket(t, cb->args[2]); @@ -960,7 +959,7 @@ type_pf_tlist(const struct ip_set *set, if (!nested) { if (cb->args[2] == first) { nla_nest_cancel(skb, atd); - return -EFAULT; + return -EMSGSIZE; } else goto nla_put_failure; } @@ -982,6 +981,7 @@ nla_put_failure: pr_warning("Can't list set %s: one bucket does not fit into " "a message. Please report it!\n", set->name); cb->args[2] = 0; + return -EMSGSIZE; } return 0; } diff --git a/extensions/ipset-6/ip_set_bitmap_ip.c b/extensions/ipset-6/ip_set_bitmap_ip.c index e011864..41cfded 100644 --- a/extensions/ipset-6/ip_set_bitmap_ip.c +++ b/extensions/ipset-6/ip_set_bitmap_ip.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -33,8 +32,7 @@ MODULE_AUTHOR("Jozsef Kadlecsik "); MODULE_DESCRIPTION("bitmap:ip type of IP sets"); MODULE_ALIAS("ip_set_bitmap:ip"); -/* Base variant */ - +/* Type structure */ struct bitmap_ip { void *members; /* the set members */ u32 first_ip; /* host byte order, included in range */ @@ -43,43 +41,188 @@ struct bitmap_ip { u32 hosts; /* number of hosts in a subnet */ size_t memsize; /* members size */ u8 netmask; /* subnet netmask */ + u32 timeout; /* timeout parameter */ + struct timer_list gc; /* garbage collection */ }; +/* Base variant */ + static inline u32 ip_to_id(const struct bitmap_ip *m, u32 ip) { return ((ip & ip_set_hostmask(m->netmask)) - m->first_ip)/m->hosts; } -static inline int -bitmap_ip_test(const struct bitmap_ip *map, u32 id) +static int +bitmap_ip_test(struct ip_set *set, void *value, u32 timeout) { + const struct bitmap_ip *map = set->data; + u16 id = *(u16 *)value; + return !!test_bit(id, map->members); } -static inline int -bitmap_ip_add(struct bitmap_ip *map, u32 id) +static int +bitmap_ip_add(struct ip_set *set, void *value, u32 timeout) { + struct bitmap_ip *map = set->data; + u16 id = *(u16 *)value; + if (test_and_set_bit(id, map->members)) return -IPSET_ERR_EXIST; return 0; } -static inline int -bitmap_ip_del(struct bitmap_ip *map, u32 id) +static int +bitmap_ip_del(struct ip_set *set, void *value, u32 timeout) { + struct bitmap_ip *map = set->data; + u16 id = *(u16 *)value; + if (!test_and_clear_bit(id, map->members)) return -IPSET_ERR_EXIST; return 0; } +static int +bitmap_ip_list(const struct ip_set *set, + struct sk_buff *skb, struct netlink_callback *cb) +{ + const struct bitmap_ip *map = set->data; + struct nlattr *atd, *nested; + u32 id, first = cb->args[2]; + + atd = ipset_nest_start(skb, IPSET_ATTR_ADT); + if (!atd) + return -EMSGSIZE; + for (; cb->args[2] < map->elements; cb->args[2]++) { + id = cb->args[2]; + if (!test_bit(id, map->members)) + continue; + nested = ipset_nest_start(skb, IPSET_ATTR_DATA); + if (!nested) { + if (id == first) { + nla_nest_cancel(skb, atd); + return -EMSGSIZE; + } else + goto nla_put_failure; + } + NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, + htonl(map->first_ip + id * map->hosts)); + 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); + if (unlikely(id == first)) { + cb->args[2] = 0; + return -EMSGSIZE; + } + return 0; +} + +/* Timeout variant */ + +static int +bitmap_ip_ttest(struct ip_set *set, void *value, u32 timeout) +{ + const struct bitmap_ip *map = set->data; + const unsigned long *members = map->members; + u16 id = *(u16 *)value; + + return ip_set_timeout_test(members[id]); +} + +static int +bitmap_ip_tadd(struct ip_set *set, void *value, u32 timeout) +{ + struct bitmap_ip *map = set->data; + unsigned long *members = map->members; + u16 id = *(u16 *)value; + + if (ip_set_timeout_test(members[id])) + return -IPSET_ERR_EXIST; + + members[id] = ip_set_timeout_set(timeout); + + return 0; +} + +static int +bitmap_ip_tdel(struct ip_set *set, void *value, u32 timeout) +{ + struct bitmap_ip *map = set->data; + unsigned long *members = map->members; + u16 id = *(u16 *)value; + int ret = -IPSET_ERR_EXIST; + + if (ip_set_timeout_test(members[id])) + ret = 0; + + members[id] = IPSET_ELEM_UNSET; + return ret; +} + +static int +bitmap_ip_tlist(const struct ip_set *set, + struct sk_buff *skb, struct netlink_callback *cb) +{ + const struct bitmap_ip *map = set->data; + struct nlattr *adt, *nested; + u32 id, first = cb->args[2]; + const unsigned long *members = map->members; + + adt = ipset_nest_start(skb, IPSET_ATTR_ADT); + if (!adt) + return -EMSGSIZE; + for (; cb->args[2] < map->elements; cb->args[2]++) { + id = cb->args[2]; + if (!ip_set_timeout_test(members[id])) + continue; + nested = ipset_nest_start(skb, IPSET_ATTR_DATA); + if (!nested) { + if (id == first) { + nla_nest_cancel(skb, adt); + return -EMSGSIZE; + } else + goto nla_put_failure; + } + NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, + htonl(map->first_ip + id * map->hosts)); + NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, + htonl(ip_set_timeout_get(members[id]))); + ipset_nest_end(skb, nested); + } + ipset_nest_end(skb, adt); + + /* Set listing finished */ + cb->args[2] = 0; + + return 0; + +nla_put_failure: + nla_nest_cancel(skb, nested); + ipset_nest_end(skb, adt); + if (unlikely(id == first)) { + cb->args[2] = 0; + return -EMSGSIZE; + } + return 0; +} + static int bitmap_ip_kadt(struct ip_set *set, const struct sk_buff *skb, enum ipset_adt adt, u8 pf, u8 dim, u8 flags) { struct bitmap_ip *map = set->data; + ipset_adtfn adtfn = set->variant->adt[adt]; u32 ip; ip = ntohl(ip4addr(skb, flags & IPSET_DIM_ONE_SRC)); @@ -88,40 +231,21 @@ bitmap_ip_kadt(struct ip_set *set, const struct sk_buff *skb, ip = ip_to_id(map, ip); - switch (adt) { - case IPSET_TEST: - return bitmap_ip_test(map, ip); - case IPSET_ADD: - return bitmap_ip_add(map, ip); - case IPSET_DEL: - return bitmap_ip_del(map, ip); - default: - return -EINVAL; - } + return adtfn(set, &ip, map->timeout); } -static const struct nla_policy bitmap_ip_adt_policy[IPSET_ATTR_ADT_MAX+1] = { - [IPSET_ATTR_IP] = { .type = NLA_NESTED }, - [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, - [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, - [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, - [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, -}; - static int -bitmap_ip_uadt(struct ip_set *set, struct nlattr *head, int len, +bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt, u32 *lineno, u32 flags) { struct bitmap_ip *map = set->data; - struct nlattr *tb[IPSET_ATTR_ADT_MAX+1]; + ipset_adtfn adtfn = set->variant->adt[adt]; + u32 timeout = map->timeout; u32 ip, ip_to, id; int ret = 0; - if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len, - bitmap_ip_adt_policy)) - return -IPSET_ERR_PROTOCOL; - - if (unlikely(!tb[IPSET_ATTR_IP])) + if (unlikely(!tb[IPSET_ATTR_IP] || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) return -IPSET_ERR_PROTOCOL; if (tb[IPSET_ATTR_LINENO]) @@ -134,13 +258,16 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *head, int len, if (ip < map->first_ip || ip > map->last_ip) return -IPSET_ERR_BITMAP_RANGE; - /* Set was defined without timeout support: - * don't ignore the attribute silently */ - if (tb[IPSET_ATTR_TIMEOUT]) - return -IPSET_ERR_TIMEOUT; + if (tb[IPSET_ATTR_TIMEOUT]) { + if (!with_timeout(map->timeout)) + return -IPSET_ERR_TIMEOUT; + timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); + } - if (adt == IPSET_TEST) - return bitmap_ip_test(map, ip_to_id(map, ip)); + if (adt == IPSET_TEST) { + id = ip_to_id(map, ip); + return adtfn(set, &id, timeout); + } if (tb[IPSET_ATTR_IP_TO]) { ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); @@ -166,8 +293,7 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *head, int len, for (; !before(ip_to, ip); ip += map->hosts) { id = ip_to_id(map, ip); - ret = adt == IPSET_ADD ? bitmap_ip_add(map, id) - : bitmap_ip_del(map, id); + ret = adtfn(set, &id, timeout);; if (ret && !ip_set_eexist(ret, flags)) return ret; @@ -182,6 +308,9 @@ bitmap_ip_destroy(struct ip_set *set) { struct bitmap_ip *map = set->data; + if (with_timeout(map->timeout)) + del_timer_sync(&map->gc); + ip_set_free(map->members); kfree(map); @@ -213,49 +342,13 @@ bitmap_ip_head(struct ip_set *set, struct sk_buff *skb) htonl(atomic_read(&set->ref) - 1)); NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, htonl(sizeof(*map) + map->memsize)); + if (with_timeout(map->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 -bitmap_ip_list(const struct ip_set *set, - struct sk_buff *skb, struct netlink_callback *cb) -{ - const struct bitmap_ip *map = set->data; - struct nlattr *atd, *nested; - u32 id, first = cb->args[2]; - - atd = ipset_nest_start(skb, IPSET_ATTR_ADT); - if (!atd) - return -EFAULT; - for (; cb->args[2] < map->elements; cb->args[2]++) { - id = cb->args[2]; - if (!bitmap_ip_test(map, 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; - } - NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, - htonl(map->first_ip + id * map->hosts)); - 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; + return -EMSGSIZE; } static bool @@ -266,12 +359,18 @@ bitmap_ip_same_set(const struct ip_set *a, const struct ip_set *b) return x->first_ip == y->first_ip && x->last_ip == y->last_ip && - x->netmask == y->netmask; + x->netmask == y->netmask && + x->timeout == y->timeout; } static const struct ip_set_type_variant bitmap_ip = { .kadt = bitmap_ip_kadt, .uadt = bitmap_ip_uadt, + .adt = { + [IPSET_ADD] = bitmap_ip_add, + [IPSET_DEL] = bitmap_ip_del, + [IPSET_TEST] = bitmap_ip_test, + }, .destroy = bitmap_ip_destroy, .flush = bitmap_ip_flush, .head = bitmap_ip_head, @@ -279,261 +378,26 @@ static const struct ip_set_type_variant bitmap_ip = { .same_set = bitmap_ip_same_set, }; -/* Timeout variant */ - -struct bitmap_ip_timeout { - unsigned long *members; /* the set members */ - u32 first_ip; /* host byte order, included in range */ - u32 last_ip; /* host byte order, included in range */ - u32 elements; /* number of max elements in the set */ - u32 hosts; /* number of hosts in a subnet */ - size_t memsize; /* members size */ - u8 netmask; /* subnet netmask */ - - u32 timeout; /* timeout parameter */ - struct timer_list gc; /* garbage collection */ -}; - -static inline bool -bitmap_ip_timeout_test(const struct bitmap_ip_timeout *map, u32 id) -{ - return ip_set_timeout_test(map->members[id]); -} - -static inline int -bitmap_ip_timeout_add(struct bitmap_ip_timeout *map, - u32 id, u32 timeout) -{ - if (bitmap_ip_timeout_test(map, id)) - return -IPSET_ERR_EXIST; - - map->members[id] = ip_set_timeout_set(timeout); - - return 0; -} - -static inline int -bitmap_ip_timeout_del(struct bitmap_ip_timeout *map, u32 id) -{ - int ret = -IPSET_ERR_EXIST; - - if (bitmap_ip_timeout_test(map, id)) - ret = 0; - - map->members[id] = IPSET_ELEM_UNSET; - return ret; -} - -static int -bitmap_ip_timeout_kadt(struct ip_set *set, const struct sk_buff *skb, - enum ipset_adt adt, u8 pf, u8 dim, u8 flags) -{ - struct bitmap_ip_timeout *map = set->data; - u32 ip; - - ip = ntohl(ip4addr(skb, flags & IPSET_DIM_ONE_SRC)); - if (ip < map->first_ip || ip > map->last_ip) - return -IPSET_ERR_BITMAP_RANGE; - - ip = ip_to_id((const struct bitmap_ip *)map, ip); - - switch (adt) { - case IPSET_TEST: - return bitmap_ip_timeout_test(map, ip); - case IPSET_ADD: - return bitmap_ip_timeout_add(map, ip, map->timeout); - case IPSET_DEL: - return bitmap_ip_timeout_del(map, ip); - default: - return -EINVAL; - } -} - -static int -bitmap_ip_timeout_uadt(struct ip_set *set, struct nlattr *head, int len, - enum ipset_adt adt, u32 *lineno, u32 flags) -{ - struct bitmap_ip_timeout *map = set->data; - struct nlattr *tb[IPSET_ATTR_ADT_MAX+1]; - u32 ip, ip_to, id, timeout = map->timeout; - int ret = 0; - - if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len, - bitmap_ip_adt_policy)) - return -IPSET_ERR_PROTOCOL; - - if (unlikely(!tb[IPSET_ATTR_IP] || - !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) - return -IPSET_ERR_PROTOCOL; - - if (tb[IPSET_ATTR_LINENO]) - *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - - ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &ip); - if (ret) - return ret; - - if (ip < map->first_ip || ip > map->last_ip) - return -IPSET_ERR_BITMAP_RANGE; - - if (adt == IPSET_TEST) - return bitmap_ip_timeout_test(map, - ip_to_id((const struct bitmap_ip *)map, ip)); - - if (tb[IPSET_ATTR_IP_TO]) { - ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); - if (ret) - return ret; - if (ip > ip_to) { - swap(ip, ip_to); - if (ip < map->first_ip) - return -IPSET_ERR_BITMAP_RANGE; - } - } else if (tb[IPSET_ATTR_CIDR]) { - u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); - - if (cidr > 32) - return -IPSET_ERR_INVALID_CIDR; - ip &= ip_set_hostmask(cidr); - ip_to = ip | ~ip_set_hostmask(cidr); - } else - ip_to = ip; - - if (ip_to > map->last_ip) - return -IPSET_ERR_BITMAP_RANGE; - - if (tb[IPSET_ATTR_TIMEOUT]) - timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); - - for (; !before(ip_to, ip); ip += map->hosts) { - id = ip_to_id((const struct bitmap_ip *)map, ip); - ret = adt == IPSET_ADD - ? bitmap_ip_timeout_add(map, id, timeout) - : bitmap_ip_timeout_del(map, id); - - if (ret && !ip_set_eexist(ret, flags)) - return ret; - else - ret = 0; - } - return ret; -} - -static void -bitmap_ip_timeout_destroy(struct ip_set *set) -{ - struct bitmap_ip_timeout *map = set->data; - - del_timer_sync(&map->gc); - ip_set_free(map->members); - kfree(map); - - set->data = NULL; -} - -static void -bitmap_ip_timeout_flush(struct ip_set *set) -{ - struct bitmap_ip_timeout *map = set->data; - - memset(map->members, IPSET_ELEM_UNSET, map->memsize); -} - -static int -bitmap_ip_timeout_head(struct ip_set *set, struct sk_buff *skb) -{ - const struct bitmap_ip_timeout *map = set->data; - struct nlattr *nested; - - nested = ipset_nest_start(skb, IPSET_ATTR_DATA); - if (!nested) - goto nla_put_failure; - NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, htonl(map->first_ip)); - NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip)); - if (map->netmask != 32) - NLA_PUT_U8(skb, IPSET_ATTR_NETMASK, map->netmask); - NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout)); - NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, - htonl(atomic_read(&set->ref) - 1)); - NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, - htonl(sizeof(*map) + map->memsize)); - ipset_nest_end(skb, nested); - - return 0; -nla_put_failure: - return -EFAULT; -} - -static int -bitmap_ip_timeout_list(const struct ip_set *set, - struct sk_buff *skb, struct netlink_callback *cb) -{ - const struct bitmap_ip_timeout *map = set->data; - struct nlattr *adt, *nested; - u32 id, first = cb->args[2]; - const unsigned long *table = map->members; - - adt = ipset_nest_start(skb, IPSET_ATTR_ADT); - if (!adt) - return -EFAULT; - for (; cb->args[2] < map->elements; cb->args[2]++) { - id = cb->args[2]; - if (!bitmap_ip_timeout_test(map, id)) - continue; - nested = ipset_nest_start(skb, IPSET_ATTR_DATA); - if (!nested) { - if (id == first) { - nla_nest_cancel(skb, adt); - return -EFAULT; - } else - goto nla_put_failure; - } - NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, - htonl(map->first_ip + id * map->hosts)); - NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, - htonl(ip_set_timeout_get(table[id]))); - ipset_nest_end(skb, nested); - } - ipset_nest_end(skb, adt); - - /* Set listing finished */ - cb->args[2] = 0; - - return 0; - -nla_put_failure: - nla_nest_cancel(skb, nested); - ipset_nest_end(skb, adt); - return 0; -} - -static bool -bitmap_ip_timeout_same_set(const struct ip_set *a, const struct ip_set *b) -{ - const struct bitmap_ip_timeout *x = a->data; - const struct bitmap_ip_timeout *y = b->data; - - return x->first_ip == y->first_ip && - x->last_ip == y->last_ip && - x->netmask == y->netmask && - x->timeout == y->timeout; -} - -static const struct ip_set_type_variant bitmap_ip_timeout = { - .kadt = bitmap_ip_timeout_kadt, - .uadt = bitmap_ip_timeout_uadt, - .destroy = bitmap_ip_timeout_destroy, - .flush = bitmap_ip_timeout_flush, - .head = bitmap_ip_timeout_head, - .list = bitmap_ip_timeout_list, - .same_set = bitmap_ip_timeout_same_set, +static const struct ip_set_type_variant bitmap_tip = { + .kadt = bitmap_ip_kadt, + .uadt = bitmap_ip_uadt, + .adt = { + [IPSET_ADD] = bitmap_ip_tadd, + [IPSET_DEL] = bitmap_ip_tdel, + [IPSET_TEST] = bitmap_ip_ttest, + }, + .destroy = bitmap_ip_destroy, + .flush = bitmap_ip_flush, + .head = bitmap_ip_head, + .list = bitmap_ip_tlist, + .same_set = bitmap_ip_same_set, }; static void bitmap_ip_gc(unsigned long ul_set) { struct ip_set *set = (struct ip_set *) ul_set; - struct bitmap_ip_timeout *map = set->data; + struct bitmap_ip *map = set->data; unsigned long *table = map->members; u32 id; @@ -552,7 +416,7 @@ bitmap_ip_gc(unsigned long ul_set) static void bitmap_ip_gc_init(struct ip_set *set) { - struct bitmap_ip_timeout *map = set->data; + struct bitmap_ip *map = set->data; init_timer(&map->gc); map->gc.data = (unsigned long) set; @@ -563,21 +427,12 @@ bitmap_ip_gc_init(struct ip_set *set) /* Create bitmap:ip type of sets */ -static const struct nla_policy -bitmap_ip_create_policy[IPSET_ATTR_CREATE_MAX+1] = { - [IPSET_ATTR_IP] = { .type = NLA_NESTED }, - [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, - [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, - [IPSET_ATTR_NETMASK] = { .type = NLA_U8 }, - [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, -}; - static bool init_map_ip(struct ip_set *set, struct bitmap_ip *map, u32 first_ip, u32 last_ip, u32 elements, u32 hosts, u8 netmask) { - map->members = ip_set_alloc(map->memsize, GFP_KERNEL); + map->members = ip_set_alloc(map->memsize); if (!map->members) return false; map->first_ip = first_ip; @@ -585,6 +440,7 @@ init_map_ip(struct ip_set *set, struct bitmap_ip *map, map->elements = elements; map->hosts = hosts; map->netmask = netmask; + map->timeout = IPSET_NO_TIMEOUT; set->data = map; set->family = AF_INET; @@ -593,18 +449,13 @@ init_map_ip(struct ip_set *set, struct bitmap_ip *map, } static int -bitmap_ip_create(struct ip_set *set, struct nlattr *head, int len, - u32 flags) +bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags) { - struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1]; + struct bitmap_ip *map; u32 first_ip, last_ip, hosts, elements; u8 netmask = 32; int ret; - if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len, - bitmap_ip_create_policy)) - return -IPSET_ERR_PROTOCOL; - if (unlikely(!tb[IPSET_ATTR_IP] || !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) return -IPSET_ERR_PROTOCOL; @@ -664,37 +515,27 @@ bitmap_ip_create(struct ip_set *set, struct nlattr *head, int len, pr_debug("hosts %u, elements %u\n", hosts, elements); + map = kzalloc(sizeof(*map), GFP_KERNEL); + if (!map) + return -ENOMEM; + if (tb[IPSET_ATTR_TIMEOUT]) { - struct bitmap_ip_timeout *map; - - map = kzalloc(sizeof(*map), GFP_KERNEL); - if (!map) - return -ENOMEM; - map->memsize = elements * sizeof(unsigned long); - if (!init_map_ip(set, (struct bitmap_ip *)map, - first_ip, last_ip, + if (!init_map_ip(set, map, first_ip, last_ip, elements, hosts, netmask)) { kfree(map); return -ENOMEM; } map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); - set->variant = &bitmap_ip_timeout; + set->variant = &bitmap_tip; bitmap_ip_gc_init(set); } else { - struct bitmap_ip *map; - - map = kzalloc(sizeof(*map), GFP_KERNEL); - if (!map) - return -ENOMEM; - map->memsize = bitmap_bytes(0, elements - 1); - if (!init_map_ip(set, map, - first_ip, last_ip, + if (!init_map_ip(set, map, first_ip, last_ip, elements, hosts, netmask)) { kfree(map); return -ENOMEM; @@ -713,6 +554,20 @@ static struct ip_set_type bitmap_ip_type __read_mostly = { .family = AF_INET, .revision = 0, .create = bitmap_ip_create, + .create_policy = { + [IPSET_ATTR_IP] = { .type = NLA_NESTED }, + [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, + [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, + [IPSET_ATTR_NETMASK] = { .type = NLA_U8 }, + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, + }, + .adt_policy = { + [IPSET_ATTR_IP] = { .type = NLA_NESTED }, + [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, + [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, + [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, + }, .me = THIS_MODULE, }; diff --git a/extensions/ipset-6/ip_set_bitmap_ipmac.c b/extensions/ipset-6/ip_set_bitmap_ipmac.c index 7363527..50fcb3f 100644 --- a/extensions/ipset-6/ip_set_bitmap_ipmac.c +++ b/extensions/ipset-6/ip_set_bitmap_ipmac.c @@ -15,9 +15,6 @@ #include #include #include -#include -#include -#include #include #include #include @@ -175,7 +172,7 @@ bitmap_ipmac_list(const struct ip_set *set, atd = ipset_nest_start(skb, IPSET_ATTR_ADT); if (!atd) - return -EFAULT; + return -EMSGSIZE; for (; cb->args[2] <= last; cb->args[2]++) { id = cb->args[2]; elem = bitmap_ipmac_elem(map, id); @@ -185,7 +182,7 @@ bitmap_ipmac_list(const struct ip_set *set, if (!nested) { if (id == first) { nla_nest_cancel(skb, atd); - return -EFAULT; + return -EMSGSIZE; } else goto nla_put_failure; } @@ -205,6 +202,10 @@ bitmap_ipmac_list(const struct ip_set *set, nla_put_failure: nla_nest_cancel(skb, nested); ipset_nest_end(skb, atd); + if (unlikely(id == first)) { + cb->args[2] = 0; + return -EMSGSIZE; + } return 0; } @@ -298,7 +299,7 @@ bitmap_ipmac_tlist(const struct ip_set *set, atd = ipset_nest_start(skb, IPSET_ATTR_ADT); if (!atd) - return -EFAULT; + return -EMSGSIZE; for (; cb->args[2] <= last; cb->args[2]++) { id = cb->args[2]; elem = bitmap_ipmac_elem(map, id); @@ -308,7 +309,7 @@ bitmap_ipmac_tlist(const struct ip_set *set, if (!nested) { if (id == first) { nla_nest_cancel(skb, atd); - return -EFAULT; + return -EMSGSIZE; } else goto nla_put_failure; } @@ -331,7 +332,7 @@ bitmap_ipmac_tlist(const struct ip_set *set, nla_put_failure: nla_nest_cancel(skb, nested); ipset_nest_end(skb, atd); - return 0; + return -EMSGSIZE; } static int @@ -357,29 +358,16 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb, return adtfn(set, &data, map->timeout); } -static const struct nla_policy -bitmap_ipmac_adt_policy[IPSET_ATTR_ADT_MAX + 1] = { - [IPSET_ATTR_IP] = { .type = NLA_NESTED }, - [IPSET_ATTR_ETHER] = { .type = NLA_BINARY, .len = ETH_ALEN }, - [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, - [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, -}; - static int -bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *head, int len, +bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt, u32 *lineno, u32 flags) { const struct bitmap_ipmac *map = set->data; - struct nlattr *tb[IPSET_ATTR_ADT_MAX+1]; ipset_adtfn adtfn = set->variant->adt[adt]; struct ipmac data; u32 timeout = map->timeout; int ret = 0; - if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len, - bitmap_ipmac_adt_policy)) - return -IPSET_ERR_PROTOCOL; - if (unlikely(!tb[IPSET_ATTR_IP] || !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) return -IPSET_ERR_PROTOCOL; @@ -457,7 +445,7 @@ bitmap_ipmac_head(struct ip_set *set, struct sk_buff *skb) return 0; nla_put_failure: - return -EFAULT; + return -EMSGSIZE; } static bool @@ -538,20 +526,11 @@ bitmap_ipmac_gc_init(struct ip_set *set) /* Create bitmap:ip,mac type of sets */ -static const struct nla_policy -bitmap_ipmac_create_policy[IPSET_ATTR_CREATE_MAX+1] = { - [IPSET_ATTR_IP] = { .type = NLA_NESTED }, - [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, - [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, - [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, -}; - static bool init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map, u32 first_ip, u32 last_ip) { - map->members = ip_set_alloc((last_ip - first_ip + 1) * map->dsize, - GFP_KERNEL); + map->members = ip_set_alloc((last_ip - first_ip + 1) * map->dsize); if (!map->members) return false; map->first_ip = first_ip; @@ -565,18 +544,13 @@ init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map, } static int -bitmap_ipmac_create(struct ip_set *set, struct nlattr *head, int len, +bitmap_ipmac_create(struct ip_set *set, struct nlattr *tb[], u32 flags) { - struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1]; u32 first_ip, last_ip, elements; struct bitmap_ipmac *map; int ret; - if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len, - bitmap_ipmac_create_policy)) - return -IPSET_ERR_PROTOCOL; - if (unlikely(!tb[IPSET_ATTR_IP] || !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) return -IPSET_ERR_PROTOCOL; @@ -647,6 +621,18 @@ static struct ip_set_type bitmap_ipmac_type = { .family = AF_INET, .revision = 0, .create = bitmap_ipmac_create, + .create_policy = { + [IPSET_ATTR_IP] = { .type = NLA_NESTED }, + [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, + [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, + }, + .adt_policy = { + [IPSET_ATTR_IP] = { .type = NLA_NESTED }, + [IPSET_ATTR_ETHER] = { .type = NLA_BINARY, .len = ETH_ALEN }, + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, + [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, + }, .me = THIS_MODULE, }; diff --git a/extensions/ipset-6/ip_set_bitmap_port.c b/extensions/ipset-6/ip_set_bitmap_port.c index 5c5c6f3..01dc2ff 100644 --- a/extensions/ipset-6/ip_set_bitmap_port.c +++ b/extensions/ipset-6/ip_set_bitmap_port.c @@ -9,13 +9,8 @@ #include #include -#include -#include #include #include -#include -#include -#include #include #include #include @@ -32,24 +27,33 @@ MODULE_AUTHOR("Jozsef Kadlecsik "); MODULE_DESCRIPTION("bitmap:port type of IP sets"); MODULE_ALIAS("ip_set_bitmap:port"); -/* Base variant */ - +/* Type structure */ struct bitmap_port { void *members; /* the set members */ u16 first_port; /* host byte order, included in range */ u16 last_port; /* host byte order, included in range */ size_t memsize; /* members size */ + u32 timeout; /* timeout parameter */ + struct timer_list gc; /* garbage collection */ }; -static inline int -bitmap_port_test(const struct bitmap_port *map, u16 id) +/* Base variant */ + +static int +bitmap_port_test(struct ip_set *set, void *value, u32 timeout) { + const struct bitmap_port *map = set->data; + u16 id = *(u16 *)value; + return !!test_bit(id, map->members); } -static inline int -bitmap_port_add(struct bitmap_port *map, u16 id) +static int +bitmap_port_add(struct ip_set *set, void *value, u32 timeout) { + struct bitmap_port *map = set->data; + u16 id = *(u16 *)value; + if (test_and_set_bit(id, map->members)) return -IPSET_ERR_EXIST; @@ -57,19 +61,157 @@ bitmap_port_add(struct bitmap_port *map, u16 id) } static int -bitmap_port_del(struct bitmap_port *map, u16 id) +bitmap_port_del(struct ip_set *set, void *value, u32 timeout) { + struct bitmap_port *map = set->data; + u16 id = *(u16 *)value; + if (!test_and_clear_bit(id, map->members)) return -IPSET_ERR_EXIST; return 0; } +static int +bitmap_port_list(const struct ip_set *set, + struct sk_buff *skb, struct netlink_callback *cb) +{ + const struct bitmap_port *map = set->data; + struct nlattr *atd, *nested; + u16 id, first = cb->args[2]; + u16 last = map->last_port - map->first_port; + + atd = ipset_nest_start(skb, IPSET_ATTR_ADT); + if (!atd) + return -EMSGSIZE; + for (; cb->args[2] <= last; cb->args[2]++) { + id = cb->args[2]; + if (!test_bit(id, map->members)) + continue; + nested = ipset_nest_start(skb, IPSET_ATTR_DATA); + if (!nested) { + if (id == first) { + nla_nest_cancel(skb, atd); + return -EMSGSIZE; + } else + goto nla_put_failure; + } + NLA_PUT_NET16(skb, IPSET_ATTR_PORT, + htons(map->first_port + id)); + 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); + if (unlikely(id == first)) { + cb->args[2] = 0; + return -EMSGSIZE; + } + return 0; +} + +/* Timeout variant */ + +static int +bitmap_port_ttest(struct ip_set *set, void *value, u32 timeout) +{ + const struct bitmap_port *map = set->data; + const unsigned long *members = map->members; + u16 id = *(u16 *)value; + + return ip_set_timeout_test(members[id]); +} + +static int +bitmap_port_tadd(struct ip_set *set, void *value, u32 timeout) +{ + struct bitmap_port *map = set->data; + unsigned long *members = map->members; + u16 id = *(u16 *)value; + + if (ip_set_timeout_test(members[id])) + return -IPSET_ERR_EXIST; + + members[id] = ip_set_timeout_set(timeout); + + return 0; +} + +static int +bitmap_port_tdel(struct ip_set *set, void *value, u32 timeout) +{ + struct bitmap_port *map = set->data; + unsigned long *members = map->members; + u16 id = *(u16 *)value; + int ret = -IPSET_ERR_EXIST; + + if (ip_set_timeout_test(members[id])) + ret = 0; + + members[id] = IPSET_ELEM_UNSET; + return ret; +} + +static int +bitmap_port_tlist(const struct ip_set *set, + struct sk_buff *skb, struct netlink_callback *cb) +{ + const struct bitmap_port *map = set->data; + struct nlattr *adt, *nested; + u16 id, first = cb->args[2]; + u16 last = map->last_port - map->first_port; + const unsigned long *members = map->members; + + adt = ipset_nest_start(skb, IPSET_ATTR_ADT); + if (!adt) + return -EMSGSIZE; + for (; cb->args[2] <= last; cb->args[2]++) { + id = cb->args[2]; + if (!ip_set_timeout_test(members[id])) + continue; + nested = ipset_nest_start(skb, IPSET_ATTR_DATA); + if (!nested) { + if (id == first) { + nla_nest_cancel(skb, adt); + return -EMSGSIZE; + } else + goto nla_put_failure; + } + NLA_PUT_NET16(skb, IPSET_ATTR_PORT, + htons(map->first_port + id)); + NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, + htonl(ip_set_timeout_get(members[id]))); + ipset_nest_end(skb, nested); + } + ipset_nest_end(skb, adt); + + /* Set listing finished */ + cb->args[2] = 0; + + return 0; + +nla_put_failure: + nla_nest_cancel(skb, nested); + ipset_nest_end(skb, adt); + if (unlikely(id == first)) { + cb->args[2] = 0; + return -EMSGSIZE; + } + return 0; +} + static int bitmap_port_kadt(struct ip_set *set, const struct sk_buff *skb, enum ipset_adt adt, u8 pf, u8 dim, u8 flags) { struct bitmap_port *map = set->data; + ipset_adtfn adtfn = set->variant->adt[adt]; __be16 __port; u16 port = 0; @@ -83,41 +225,23 @@ bitmap_port_kadt(struct ip_set *set, const struct sk_buff *skb, port -= map->first_port; - switch (adt) { - case IPSET_TEST: - return bitmap_port_test(map, port); - case IPSET_ADD: - return bitmap_port_add(map, port); - case IPSET_DEL: - return bitmap_port_del(map, port); - default: - return -EINVAL; - } + return adtfn(set, &port, map->timeout); } -static const struct nla_policy bitmap_port_adt_policy[IPSET_ATTR_ADT_MAX+1] = { - [IPSET_ATTR_PORT] = { .type = NLA_U16 }, - [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 }, - [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, - [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, -}; - static int -bitmap_port_uadt(struct ip_set *set, struct nlattr *head, int len, +bitmap_port_uadt(struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt, u32 *lineno, u32 flags) { struct bitmap_port *map = set->data; - struct nlattr *tb[IPSET_ATTR_ADT_MAX+1]; + ipset_adtfn adtfn = set->variant->adt[adt]; + u32 timeout = map->timeout; u32 port; /* wraparound */ u16 id, port_to; int ret = 0; - if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len, - bitmap_port_adt_policy)) - return -IPSET_ERR_PROTOCOL; - if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || - !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO))) + !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) return -IPSET_ERR_PROTOCOL; if (tb[IPSET_ATTR_LINENO]) @@ -127,11 +251,16 @@ bitmap_port_uadt(struct ip_set *set, struct nlattr *head, int len, if (port < map->first_port || port > map->last_port) return -IPSET_ERR_BITMAP_RANGE; - if (tb[IPSET_ATTR_TIMEOUT]) - return -IPSET_ERR_TIMEOUT; + if (tb[IPSET_ATTR_TIMEOUT]) { + if (!with_timeout(map->timeout)) + return -IPSET_ERR_TIMEOUT; + timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); + } - if (adt == IPSET_TEST) - return bitmap_port_test(map, port - map->first_port); + if (adt == IPSET_TEST) { + id = port - map->first_port; + return adtfn(set, &id, timeout); + } if (tb[IPSET_ATTR_PORT_TO]) { port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); @@ -148,8 +277,7 @@ bitmap_port_uadt(struct ip_set *set, struct nlattr *head, int len, for (; port <= port_to; port++) { id = port - map->first_port; - ret = adt == IPSET_ADD ? bitmap_port_add(map, id) - : bitmap_port_del(map, id); + ret = adtfn(set, &id, timeout); if (ret && !ip_set_eexist(ret, flags)) return ret; @@ -164,6 +292,9 @@ bitmap_port_destroy(struct ip_set *set) { struct bitmap_port *map = set->data; + if (with_timeout(map->timeout)) + del_timer_sync(&map->gc); + ip_set_free(map->members); kfree(map); @@ -193,51 +324,13 @@ bitmap_port_head(struct ip_set *set, struct sk_buff *skb) htonl(atomic_read(&set->ref) - 1)); NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, htonl(sizeof(*map) + map->memsize)); + if (with_timeout(map->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 -bitmap_port_list(const struct ip_set *set, - struct sk_buff *skb, struct netlink_callback *cb) -{ - const struct bitmap_port *map = set->data; - struct nlattr *atd, *nested; - u16 id, first = cb->args[2]; - u16 last = map->last_port - map->first_port; - - atd = ipset_nest_start(skb, IPSET_ATTR_ADT); - if (!atd) - return -EFAULT; - for (; cb->args[2] <= last; cb->args[2]++) { - id = cb->args[2]; - if (!test_bit(id, map->members)) - 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; - } - NLA_PUT_NET16(skb, IPSET_ATTR_PORT, - htons(map->first_port + id)); - 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; + return -EMSGSIZE; } static bool @@ -247,12 +340,18 @@ bitmap_port_same_set(const struct ip_set *a, const struct ip_set *b) const struct bitmap_port *y = b->data; return x->first_port == y->first_port && - x->last_port == y->last_port; + x->last_port == y->last_port && + x->timeout == y->timeout; } static const struct ip_set_type_variant bitmap_port = { .kadt = bitmap_port_kadt, .uadt = bitmap_port_uadt, + .adt = { + [IPSET_ADD] = bitmap_port_add, + [IPSET_DEL] = bitmap_port_del, + [IPSET_TEST] = bitmap_port_test, + }, .destroy = bitmap_port_destroy, .flush = bitmap_port_flush, .head = bitmap_port_head, @@ -260,251 +359,26 @@ static const struct ip_set_type_variant bitmap_port = { .same_set = bitmap_port_same_set, }; -/* Timeout variant */ - -struct bitmap_port_timeout { - unsigned long *members; /* the set members */ - u16 first_port; /* host byte order, included in range */ - u16 last_port; /* host byte order, included in range */ - size_t memsize; /* members size */ - - u32 timeout; /* timeout parameter */ - struct timer_list gc; /* garbage collection */ -}; - -static inline bool -bitmap_port_timeout_test(const struct bitmap_port_timeout *map, u16 id) -{ - return ip_set_timeout_test(map->members[id]); -} - -static int -bitmap_port_timeout_add(const struct bitmap_port_timeout *map, - u16 id, u32 timeout) -{ - if (bitmap_port_timeout_test(map, id)) - return -IPSET_ERR_EXIST; - - map->members[id] = ip_set_timeout_set(timeout); - - return 0; -} - -static int -bitmap_port_timeout_del(const struct bitmap_port_timeout *map, - u16 id) -{ - int ret = -IPSET_ERR_EXIST; - - if (bitmap_port_timeout_test(map, id)) - ret = 0; - - map->members[id] = IPSET_ELEM_UNSET; - return ret; -} - -static int -bitmap_port_timeout_kadt(struct ip_set *set, const struct sk_buff *skb, - enum ipset_adt adt, u8 pf, u8 dim, u8 flags) -{ - struct bitmap_port_timeout *map = set->data; - __be16 __port; - u16 port = 0; - - if (!ip_set_get_ip_port(skb, pf, flags & IPSET_DIM_ONE_SRC, &__port)) - return -EINVAL; - - port = ntohs(__port); - - if (port < map->first_port || port > map->last_port) - return -IPSET_ERR_BITMAP_RANGE; - - port -= map->first_port; - - switch (adt) { - case IPSET_TEST: - return bitmap_port_timeout_test(map, port); - case IPSET_ADD: - return bitmap_port_timeout_add(map, port, map->timeout); - case IPSET_DEL: - return bitmap_port_timeout_del(map, port); - default: - return -EINVAL; - } -} - -static int -bitmap_port_timeout_uadt(struct ip_set *set, struct nlattr *head, int len, - enum ipset_adt adt, u32 *lineno, u32 flags) -{ - const struct bitmap_port_timeout *map = set->data; - struct nlattr *tb[IPSET_ATTR_ADT_MAX+1]; - u16 id, port_to; - u32 port, timeout = map->timeout; /* wraparound */ - int ret = 0; - - if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len, - bitmap_port_adt_policy)) - return -IPSET_ERR_PROTOCOL; - - if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || - !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || - !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) - return -IPSET_ERR_PROTOCOL; - - if (tb[IPSET_ATTR_LINENO]) - *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); - - port = ip_set_get_h16(tb[IPSET_ATTR_PORT]); - if (port < map->first_port || port > map->last_port) - return -IPSET_ERR_BITMAP_RANGE; - - if (adt == IPSET_TEST) - return bitmap_port_timeout_test(map, port - map->first_port); - - if (tb[IPSET_ATTR_PORT_TO]) { - port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); - if (port > port_to) { - swap(port, port_to); - if (port < map->first_port) - return -IPSET_ERR_BITMAP_RANGE; - } - } else - port_to = port; - - if (port_to > map->last_port) - return -IPSET_ERR_BITMAP_RANGE; - - if (tb[IPSET_ATTR_TIMEOUT]) - timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); - - for (; port <= port_to; port++) { - id = port - map->first_port; - ret = adt == IPSET_ADD - ? bitmap_port_timeout_add(map, id, timeout) - : bitmap_port_timeout_del(map, id); - - if (ret && !ip_set_eexist(ret, flags)) - return ret; - else - ret = 0; - } - return ret; -} - -static void -bitmap_port_timeout_destroy(struct ip_set *set) -{ - struct bitmap_port_timeout *map = set->data; - - del_timer_sync(&map->gc); - ip_set_free(map->members); - kfree(map); - - set->data = NULL; -} - -static void -bitmap_port_timeout_flush(struct ip_set *set) -{ - struct bitmap_port_timeout *map = set->data; - - memset(map->members, 0, map->memsize); -} - -static int -bitmap_port_timeout_head(struct ip_set *set, struct sk_buff *skb) -{ - const struct bitmap_port_timeout *map = set->data; - struct nlattr *nested; - - nested = ipset_nest_start(skb, IPSET_ATTR_DATA); - if (!nested) - goto nla_put_failure; - NLA_PUT_NET16(skb, IPSET_ATTR_PORT, htons(map->first_port)); - NLA_PUT_NET16(skb, IPSET_ATTR_PORT_TO, htons(map->last_port)); - NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT , htonl(map->timeout)); - NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, - htonl(atomic_read(&set->ref) - 1)); - NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, - htonl(sizeof(*map) + map->memsize)); - ipset_nest_end(skb, nested); - - return 0; -nla_put_failure: - return -EFAULT; -} - -static int -bitmap_port_timeout_list(const struct ip_set *set, - struct sk_buff *skb, struct netlink_callback *cb) -{ - const struct bitmap_port_timeout *map = set->data; - struct nlattr *adt, *nested; - u16 id, first = cb->args[2]; - u16 last = map->last_port - map->first_port; - const unsigned long *table = map->members; - - adt = ipset_nest_start(skb, IPSET_ATTR_ADT); - if (!adt) - return -EFAULT; - for (; cb->args[2] <= last; cb->args[2]++) { - id = cb->args[2]; - if (!bitmap_port_timeout_test(map, id)) - continue; - nested = ipset_nest_start(skb, IPSET_ATTR_DATA); - if (!nested) { - if (id == first) { - nla_nest_cancel(skb, adt); - return -EFAULT; - } else - goto nla_put_failure; - } - NLA_PUT_NET16(skb, IPSET_ATTR_PORT, - htons(map->first_port + id)); - NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, - htonl(ip_set_timeout_get(table[id]))); - ipset_nest_end(skb, nested); - } - ipset_nest_end(skb, adt); - - /* Set listing finished */ - cb->args[2] = 0; - - return 0; - -nla_put_failure: - nla_nest_cancel(skb, nested); - ipset_nest_end(skb, adt); - return 0; -} - -static bool -bitmap_port_timeout_same_set(const struct ip_set *a, const struct ip_set *b) -{ - const struct bitmap_port_timeout *x = a->data; - const struct bitmap_port_timeout *y = b->data; - - return x->first_port == y->first_port && - x->last_port == y->last_port && - x->timeout == y->timeout; -} - -static const struct ip_set_type_variant bitmap_port_timeout = { - .kadt = bitmap_port_timeout_kadt, - .uadt = bitmap_port_timeout_uadt, - .destroy = bitmap_port_timeout_destroy, - .flush = bitmap_port_timeout_flush, - .head = bitmap_port_timeout_head, - .list = bitmap_port_timeout_list, - .same_set = bitmap_port_timeout_same_set, +static const struct ip_set_type_variant bitmap_tport = { + .kadt = bitmap_port_kadt, + .uadt = bitmap_port_uadt, + .adt = { + [IPSET_ADD] = bitmap_port_tadd, + [IPSET_DEL] = bitmap_port_tdel, + [IPSET_TEST] = bitmap_port_ttest, + }, + .destroy = bitmap_port_destroy, + .flush = bitmap_port_flush, + .head = bitmap_port_head, + .list = bitmap_port_tlist, + .same_set = bitmap_port_same_set, }; static void bitmap_port_gc(unsigned long ul_set) { struct ip_set *set = (struct ip_set *) ul_set; - struct bitmap_port_timeout *map = set->data; + struct bitmap_port *map = set->data; unsigned long *table = map->members; u32 id; /* wraparound */ u16 last = map->last_port - map->first_port; @@ -524,7 +398,7 @@ bitmap_port_gc(unsigned long ul_set) static void bitmap_port_gc_init(struct ip_set *set) { - struct bitmap_port_timeout *map = set->data; + struct bitmap_port *map = set->data; init_timer(&map->gc); map->gc.data = (unsigned long) set; @@ -535,22 +409,16 @@ bitmap_port_gc_init(struct ip_set *set) /* Create bitmap:ip type of sets */ -static const struct nla_policy -bitmap_port_create_policy[IPSET_ATTR_CREATE_MAX+1] = { - [IPSET_ATTR_PORT] = { .type = NLA_U16 }, - [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 }, - [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, -}; - static bool init_map_port(struct ip_set *set, struct bitmap_port *map, u16 first_port, u16 last_port) { - map->members = ip_set_alloc(map->memsize, GFP_KERNEL); + map->members = ip_set_alloc(map->memsize); if (!map->members) return false; map->first_port = first_port; map->last_port = last_port; + map->timeout = IPSET_NO_TIMEOUT; set->data = map; set->family = AF_UNSPEC; @@ -559,16 +427,12 @@ init_map_port(struct ip_set *set, struct bitmap_port *map, } static int -bitmap_port_create(struct ip_set *set, struct nlattr *head, int len, +bitmap_port_create(struct ip_set *set, struct nlattr *tb[], u32 flags) { - struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1]; + struct bitmap_port *map; u16 first_port, last_port; - if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len, - bitmap_port_create_policy)) - return -IPSET_ERR_PROTOCOL; - if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || !ip_set_attr_netorder(tb, IPSET_ATTR_PORT_TO) || !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) @@ -583,33 +447,24 @@ bitmap_port_create(struct ip_set *set, struct nlattr *head, int len, last_port = tmp; } + map = kzalloc(sizeof(*map), GFP_KERNEL); + if (!map) + return -ENOMEM; + if (tb[IPSET_ATTR_TIMEOUT]) { - struct bitmap_port_timeout *map; - - map = kzalloc(sizeof(*map), GFP_KERNEL); - if (!map) - return -ENOMEM; - map->memsize = (last_port - first_port + 1) * sizeof(unsigned long); - if (!init_map_port(set, (struct bitmap_port *) map, - first_port, last_port)) { + if (!init_map_port(set, map, first_port, last_port)) { kfree(map); return -ENOMEM; } map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); - set->variant = &bitmap_port_timeout; + set->variant = &bitmap_tport; bitmap_port_gc_init(set); } else { - struct bitmap_port *map; - - map = kzalloc(sizeof(*map), GFP_KERNEL); - if (!map) - return -ENOMEM; - map->memsize = bitmap_bytes(0, last_port - first_port); pr_debug("memsize: %zu\n", map->memsize); if (!init_map_port(set, map, first_port, last_port)) { @@ -630,6 +485,17 @@ static struct ip_set_type bitmap_port_type = { .family = AF_UNSPEC, .revision = 0, .create = bitmap_port_create, + .create_policy = { + [IPSET_ATTR_PORT] = { .type = NLA_U16 }, + [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 }, + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, + }, + .adt_policy = { + [IPSET_ATTR_PORT] = { .type = NLA_U16 }, + [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 }, + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, + [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, + }, .me = THIS_MODULE, }; diff --git a/extensions/ipset-6/ip_set_core.c b/extensions/ipset-6/ip_set_core.c index d17cffe..83da444 100644 --- a/extensions/ipset-6/ip_set_core.c +++ b/extensions/ipset-6/ip_set_core.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -196,20 +197,24 @@ EXPORT_SYMBOL_GPL(ip_set_type_unregister); /* Utility functions */ void * -ip_set_alloc(size_t size, gfp_t gfp_mask) +ip_set_alloc(size_t size) { void *members = NULL; if (size < KMALLOC_MAX_SIZE) - members = kzalloc(size, gfp_mask | __GFP_NOWARN); + members = kzalloc(size, GFP_KERNEL | __GFP_NOWARN); if (members) { pr_debug("%p: allocated with kmalloc\n", members); return members; } - members = __vmalloc(size, gfp_mask | __GFP_ZERO | __GFP_HIGHMEM, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 37) + members = __vmalloc(size, GFP_KERNEL | __GFP_ZERO | __GFP_HIGHMEM, PAGE_KERNEL); +#else + members = vzalloc(size); +#endif if (!members) return NULL; pr_debug("%p: allocated with vmalloc\n", members); @@ -249,8 +254,7 @@ ip_set_get_ipaddr4(struct nlattr *nla, __be32 *ipaddr) if (unlikely(!flag_nested(nla))) return -IPSET_ERR_PROTOCOL; - if (nla_parse(tb, IPSET_ATTR_IPADDR_MAX, nla_data(nla), nla_len(nla), - ipaddr_policy)) + if (nla_parse_nested(tb, IPSET_ATTR_IPADDR_MAX, nla, ipaddr_policy)) return -IPSET_ERR_PROTOCOL; if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_IPADDR_IPV4))) return -IPSET_ERR_PROTOCOL; @@ -268,8 +272,7 @@ ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr) if (unlikely(!flag_nested(nla))) return -IPSET_ERR_PROTOCOL; - if (nla_parse(tb, IPSET_ATTR_IPADDR_MAX, nla_data(nla), nla_len(nla), - ipaddr_policy)) + if (nla_parse_nested(tb, IPSET_ATTR_IPADDR_MAX, nla, ipaddr_policy)) return -IPSET_ERR_PROTOCOL; if (unlikely(!ip_set_attr_netorder(tb, IPSET_ATTR_IPADDR_IPV6))) return -IPSET_ERR_PROTOCOL; @@ -611,10 +614,11 @@ ip_set_create(struct sk_buff *skb, struct genl_info *info) struct ip_set *set, *clash; ip_set_id_t index = IPSET_INVALID_ID; + struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1] = {}; const char *name, *typename; u8 family, revision; u32 flags = flag_exist(info->genlhdr); - int ret = 0, len; + int ret = 0; if (unlikely(protocol_failed(attr) || attr[IPSET_ATTR_SETNAME] == NULL || @@ -659,11 +663,14 @@ ip_set_create(struct sk_buff *skb, struct genl_info *info) /* * Without holding any locks, create private part. */ - len = attr[IPSET_ATTR_DATA] ? nla_len(attr[IPSET_ATTR_DATA]) : 0; - pr_debug("data len: %u\n", len); - ret = set->type->create(set, attr[IPSET_ATTR_DATA] ? - nla_data(attr[IPSET_ATTR_DATA]) : NULL, len, - flags); + if (attr[IPSET_ATTR_DATA] && + nla_parse_nested(tb, IPSET_ATTR_CREATE_MAX, attr[IPSET_ATTR_DATA], + set->type->create_policy)) { + ret = -IPSET_ERR_PROTOCOL; + goto put_out; + } + + ret = set->type->create(set, tb, flags); if (ret != 0) goto put_out; @@ -749,7 +756,7 @@ ip_set_destroy(struct sk_buff *skb, struct genl_info *info) } else { i = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME])); if (i == IPSET_INVALID_ID) - return -EEXIST; + return -ENOENT; else if (atomic_read(&ip_set_list[i]->ref)) return -IPSET_ERR_BUSY; @@ -786,7 +793,7 @@ ip_set_flush(struct sk_buff *skb, struct genl_info *info) } else { i = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME])); if (i == IPSET_INVALID_ID) - return -EEXIST; + return -ENOENT; ip_set_flush_set(ip_set_list[i]); } @@ -820,7 +827,7 @@ ip_set_rename(struct sk_buff *skb, struct genl_info *info) set = find_set(nla_data(attr[IPSET_ATTR_SETNAME])); if (set == NULL) - return -EEXIST; + return -ENOENT; if (atomic_read(&set->ref) != 0) return -IPSET_ERR_REFERENCED; @@ -860,7 +867,7 @@ ip_set_swap(struct sk_buff *skb, struct genl_info *info) from_id = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME])); if (from_id == IPSET_INVALID_ID) - return -EEXIST; + return -ENOENT; to_id = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME2])); if (to_id == IPSET_INVALID_ID) @@ -946,7 +953,7 @@ dump_init(struct netlink_callback *cb) index = find_set_id(nla_data(cda[IPSET_ATTR_SETNAME])); if (index == IPSET_INVALID_ID) - return -EEXIST; + return -ENOENT; cb->args[0] = DUMP_ONE; cb->args[1] = index; @@ -958,16 +965,18 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb) { ip_set_id_t index = IPSET_INVALID_ID, max; struct ip_set *set = NULL; - void *nlh = NULL; + struct nlmsghdr *nlh = NULL; unsigned int flags = NETLINK_CB(cb->skb).pid ? NLM_F_MULTI : 0; int ret = 0; if (cb->args[0] == DUMP_INIT) { ret = dump_init(cb); if (ret < 0) { + nlh = nlmsg_hdr(cb->skb); /* We have to create and send the error message * manually :-( */ - netlink_ack(cb->skb, nlmsg_hdr(cb->skb), ret); + if (nlh->nlmsg_flags & NLM_F_ACK) + netlink_ack(cb->skb, nlh, ret); return ret; } } @@ -982,7 +991,7 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb) set = ip_set_list[index]; if (set == NULL) { if (cb->args[0] == DUMP_ONE) { - ret = -EEXIST; + ret = -ENOENT; goto out; } continue; @@ -1004,7 +1013,7 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb) cb->nlh->nlmsg_seq, flags, IPSET_CMD_LIST); if (!nlh) { - ret = -EFAULT; + ret = -EMSGSIZE; goto release_refcount; } NLA_PUT_U8(skb, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL); @@ -1092,19 +1101,17 @@ static const struct nla_policy ip_set_adt_policy[IPSET_ATTR_CMD_MAX + 1] = { }; static int -call_ad(struct sk_buff *skb, struct nlattr *const attr[], - struct ip_set *set, const struct nlattr *nla, - enum ipset_adt adt, u32 flags) +call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set, + struct nlattr *tb[], enum ipset_adt adt, + u32 flags, bool use_lineno) { - struct nlattr *head = nla_data(nla); - int ret, len = nla_len(nla), retried = 0; + int ret, retried = 0; u32 lineno = 0; bool eexist = flags & IPSET_FLAG_EXIST; do { write_lock_bh(&set->lock); - ret = set->variant->uadt(set, head, len, adt, - &lineno, flags); + ret = set->variant->uadt(set, tb, adt, &lineno, flags); write_unlock_bh(&set->lock); } while (ret == -EAGAIN && set->variant->resize && @@ -1112,11 +1119,38 @@ call_ad(struct sk_buff *skb, struct nlattr *const attr[], if (!ret || (ret == -IPSET_ERR_EXIST && eexist)) return 0; - if (lineno && attr[IPSET_ATTR_LINENO]) { + if (lineno && use_lineno) { /* Error in restore/batch mode: send back lineno */ - u32 *errline = nla_data(attr[IPSET_ATTR_LINENO]); + struct nlmsghdr *rep, *nlh = nlmsg_hdr(skb); + struct sk_buff *skb2; + struct nlmsgerr *errmsg; + size_t payload = sizeof(*errmsg) + nlmsg_len(nlh); + int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg)); + struct nlattr *cda[IPSET_ATTR_CMD_MAX+1]; + struct nlattr *cmdattr; + u32 *errline; + + skb2 = nlmsg_new(payload, GFP_KERNEL); + if (skb2 == NULL) + return -ENOMEM; + rep = __nlmsg_put(skb2, NETLINK_CB(skb).pid, + nlh->nlmsg_seq, NLMSG_ERROR, payload, 0); + errmsg = nlmsg_data(rep); + errmsg->error = ret; + memcpy(&errmsg->msg, nlh, nlh->nlmsg_len); + cmdattr = (void *)&errmsg->msg + min_len; + + nla_parse(cda, IPSET_ATTR_CMD_MAX, + cmdattr, nlh->nlmsg_len - min_len, + ip_set_adt_policy); + + errline = nla_data(cda[IPSET_ATTR_LINENO]); *errline = lineno; + + netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT); + /* Signal netlink not to send its ACK/errmsg. */ + return -EINTR; } return ret; @@ -1126,10 +1160,13 @@ static int ip_set_uadd(struct sk_buff *skb, struct genl_info *info) { struct nlattr *const *attr = info->attrs; + struct sock *ctnl = genl_info_net(info)->genl_sock; struct ip_set *set; + struct nlattr *tb[IPSET_ATTR_ADT_MAX+1] = {}; const struct nlattr *nla; u32 flags = flag_exist(info->genlhdr); + bool use_lineno; int ret = 0; if (unlikely(protocol_failed(attr) || @@ -1145,20 +1182,28 @@ ip_set_uadd(struct sk_buff *skb, struct genl_info *info) set = find_set(nla_data(attr[IPSET_ATTR_SETNAME])); if (set == NULL) - return -EEXIST; + return -ENOENT; + use_lineno = !!attr[IPSET_ATTR_LINENO]; if (attr[IPSET_ATTR_DATA]) { - ret = call_ad(skb, attr, - set, attr[IPSET_ATTR_DATA], IPSET_ADD, flags); + if (nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, + attr[IPSET_ATTR_DATA], + set->type->adt_policy)) + return -IPSET_ERR_PROTOCOL; + ret = call_ad(ctnl, skb, set, tb, IPSET_ADD, flags, + use_lineno); } else { int nla_rem; nla_for_each_nested(nla, attr[IPSET_ATTR_ADT], nla_rem) { + memset(tb, 0, sizeof(tb)); if (nla_type(nla) != IPSET_ATTR_DATA || - !flag_nested(nla)) + !flag_nested(nla) || + nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, nla, + set->type->adt_policy)) return -IPSET_ERR_PROTOCOL; - ret = call_ad(skb, attr, - set, nla, IPSET_ADD, flags); + ret = call_ad(ctnl, skb, set, tb, IPSET_ADD, + flags, use_lineno); if (ret < 0) return ret; } @@ -1170,10 +1215,13 @@ static int ip_set_udel(struct sk_buff *skb, struct genl_info *info) { struct nlattr *const *attr = info->attrs; + struct sock *ctnl = genl_info_net(info)->genl_sock; struct ip_set *set; + struct nlattr *tb[IPSET_ATTR_ADT_MAX+1] = {}; const struct nlattr *nla; u32 flags = flag_exist(info->genlhdr); + bool use_lineno; int ret = 0; if (unlikely(protocol_failed(attr) || @@ -1189,20 +1237,28 @@ ip_set_udel(struct sk_buff *skb, struct genl_info *info) set = find_set(nla_data(attr[IPSET_ATTR_SETNAME])); if (set == NULL) - return -EEXIST; + return -ENOENT; + use_lineno = !!attr[IPSET_ATTR_LINENO]; if (attr[IPSET_ATTR_DATA]) { - ret = call_ad(skb, attr, - set, attr[IPSET_ATTR_DATA], IPSET_DEL, flags); + if (nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, + attr[IPSET_ATTR_DATA], + set->type->adt_policy)) + return -IPSET_ERR_PROTOCOL; + ret = call_ad(ctnl, skb, set, tb, IPSET_DEL, flags, + use_lineno); } else { int nla_rem; nla_for_each_nested(nla, attr[IPSET_ATTR_ADT], nla_rem) { + memset(tb, 0, sizeof(*tb)); if (nla_type(nla) != IPSET_ATTR_DATA || - !flag_nested(nla)) + !flag_nested(nla) || + nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, nla, + set->type->adt_policy)) return -IPSET_ERR_PROTOCOL; - ret = call_ad(skb, attr, - set, nla, IPSET_DEL, flags); + ret = call_ad(ctnl, skb, set, tb, IPSET_DEL, + flags, use_lineno); if (ret < 0) return ret; } @@ -1216,6 +1272,7 @@ ip_set_utest(struct sk_buff *skb, struct genl_info *info) struct nlattr *const *attr = info->attrs; struct ip_set *set; + struct nlattr *tb[IPSET_ATTR_ADT_MAX+1] = {}; int ret = 0; if (unlikely(protocol_failed(attr) || @@ -1226,13 +1283,14 @@ ip_set_utest(struct sk_buff *skb, struct genl_info *info) set = find_set(nla_data(attr[IPSET_ATTR_SETNAME])); if (set == NULL) - return -EEXIST; + return -ENOENT; + + if (nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, attr[IPSET_ATTR_DATA], + set->type->adt_policy)) + return -IPSET_ERR_PROTOCOL; read_lock_bh(&set->lock); - ret = set->variant->uadt(set, - nla_data(attr[IPSET_ATTR_DATA]), - nla_len(attr[IPSET_ATTR_DATA]), - IPSET_TEST, NULL, 0); + ret = set->variant->uadt(set, tb, IPSET_TEST, NULL, 0); read_unlock_bh(&set->lock); /* Userspace can't trigger element to be re-added */ if (ret == -EAGAIN) @@ -1260,7 +1318,7 @@ ip_set_header(struct sk_buff *skb, struct genl_info *info) index = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME])); if (index == IPSET_INVALID_ID) - return -EEXIST; + return -ENOENT; set = ip_set_list[index]; skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); @@ -1280,7 +1338,7 @@ ip_set_header(struct sk_buff *skb, struct genl_info *info) ret = genlmsg_unicast(genl_info_net(info), skb2, NETLINK_CB(skb).pid); if (ret < 0) - return -EFAULT; + return ret; return 0; @@ -1288,7 +1346,7 @@ nla_put_failure: nlmsg_cancel(skb2, nlh2); nlmsg_failure: kfree_skb(skb2); - return -EFAULT; + return -EMSGSIZE; } /* Get type data */ @@ -1341,7 +1399,7 @@ ip_set_type(struct sk_buff *skb, struct genl_info *info) pr_debug("Send TYPE, nlmsg_len: %u\n", skb2->len); ret = genlmsg_unicast(genl_info_net(info), skb2, NETLINK_CB(skb).pid); if (ret < 0) - return -EFAULT; + return ret; return 0; @@ -1349,7 +1407,7 @@ nla_put_failure: genlmsg_cancel(skb2, nlh2); nlmsg_failure: kfree_skb(skb2); - return -EFAULT; + return -EMSGSIZE; } /* Get protocol version */ @@ -1385,7 +1443,7 @@ ip_set_protocol(struct sk_buff *skb, struct genl_info *info) ret = genlmsg_unicast(genl_info_net(info), skb2, NETLINK_CB(skb).pid); if (ret < 0) - return -EFAULT; + return ret; return 0; @@ -1393,7 +1451,7 @@ nla_put_failure: genlmsg_cancel(skb2, nlh2); nlmsg_failure: kfree_skb(skb2); - return -EFAULT; + return -EMSGSIZE; } static struct genl_ops ip_set_netlink_subsys_cb[] __read_mostly = { diff --git a/extensions/ipset-6/ip_set_getport.c b/extensions/ipset-6/ip_set_getport.c index d6cf5d2..0daf5e5 100644 --- a/extensions/ipset-6/ip_set_getport.c +++ b/extensions/ipset-6/ip_set_getport.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "ip_set_getport.h" @@ -93,21 +94,23 @@ ip_set_get_ip4_port(const struct sk_buff *skb, bool src, } EXPORT_SYMBOL_GPL(ip_set_get_ip4_port); +#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) bool ip_set_get_ip6_port(const struct sk_buff *skb, bool src, __be16 *port, u8 *proto) { - unsigned int protooff = 0; - int protocol; - unsigned short fragoff; + int protoff; + u8 nexthdr; - protocol = ipv6_find_hdr(skb, &protooff, -1, &fragoff); - if (protocol <= 0 || fragoff) + nexthdr = ipv6_hdr(skb)->nexthdr; + protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr); + if (protoff < 0) return false; - return get_port(skb, protocol, protooff, src, port, proto); + return get_port(skb, nexthdr, protoff, src, port, proto); } EXPORT_SYMBOL_GPL(ip_set_get_ip6_port); +#endif bool ip_set_get_ip_port(const struct sk_buff *skb, u8 pf, bool src, __be16 *port) @@ -118,8 +121,10 @@ ip_set_get_ip_port(const struct sk_buff *skb, u8 pf, bool src, __be16 *port) switch (pf) { case AF_INET: ret = ip_set_get_ip4_port(skb, src, port, &proto); + break; case AF_INET6: ret = ip_set_get_ip6_port(skb, src, port, &proto); + break; default: return false; } diff --git a/extensions/ipset-6/ip_set_getport.h b/extensions/ipset-6/ip_set_getport.h index 694c433..3882a81 100644 --- a/extensions/ipset-6/ip_set_getport.h +++ b/extensions/ipset-6/ip_set_getport.h @@ -3,8 +3,18 @@ extern bool ip_set_get_ip4_port(const struct sk_buff *skb, bool src, __be16 *port, u8 *proto); + +#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) extern bool ip_set_get_ip6_port(const struct sk_buff *skb, bool src, __be16 *port, u8 *proto); +#else +static inline bool ip_set_get_ip6_port(const struct sk_buff *skb, bool src, + __be16 *port, u8 *proto) +{ + return false; +} +#endif + extern bool ip_set_get_ip_port(const struct sk_buff *skb, u8 pf, bool src, __be16 *port); diff --git a/extensions/ipset-6/ip_set_hash_ip.c b/extensions/ipset-6/ip_set_hash_ip.c index 3eaa910..5bc3a9a 100644 --- a/extensions/ipset-6/ip_set_hash_ip.c +++ b/extensions/ipset-6/ip_set_hash_ip.c @@ -12,9 +12,6 @@ #include #include #include -#include -#include -#include #include #include #include @@ -127,29 +124,16 @@ hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb, return adtfn(set, &ip, h->timeout); } -static const struct nla_policy hash_ip4_adt_policy[IPSET_ATTR_ADT_MAX + 1] = { - [IPSET_ATTR_IP] = { .type = NLA_NESTED }, - [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, - [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, - [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, - [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, -}; - static int -hash_ip4_uadt(struct ip_set *set, struct nlattr *head, int len, +hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt, u32 *lineno, u32 flags) { const struct ip_set_hash *h = set->data; - struct nlattr *tb[IPSET_ATTR_ADT_MAX+1]; ipset_adtfn adtfn = set->variant->adt[adt]; u32 ip, ip_to, hosts, timeout = h->timeout; __be32 nip; int ret = 0; - if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len, - hash_ip4_adt_policy)) - return -IPSET_ERR_PROTOCOL; - if (unlikely(!tb[IPSET_ATTR_IP] || !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) return -IPSET_ERR_PROTOCOL; @@ -320,22 +304,19 @@ static const struct nla_policy hash_ip6_adt_policy[IPSET_ATTR_ADT_MAX + 1] = { }; static int -hash_ip6_uadt(struct ip_set *set, struct nlattr *head, int len, +hash_ip6_uadt(struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt, u32 *lineno, u32 flags) { const struct ip_set_hash *h = set->data; - struct nlattr *tb[IPSET_ATTR_ADT_MAX+1]; ipset_adtfn adtfn = set->variant->adt[adt]; union nf_inet_addr ip; u32 timeout = h->timeout; int ret; - if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len, - hash_ip6_adt_policy)) - return -IPSET_ERR_PROTOCOL; - if (unlikely(!tb[IPSET_ATTR_IP] || - !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || + tb[IPSET_ATTR_IP_TO] || + tb[IPSET_ATTR_CIDR])) return -IPSET_ERR_PROTOCOL; if (tb[IPSET_ATTR_LINENO]) @@ -362,20 +343,9 @@ hash_ip6_uadt(struct ip_set *set, struct nlattr *head, int len, /* Create hash:ip type of sets */ -static const struct nla_policy -hash_ip_create_policy[IPSET_ATTR_CREATE_MAX+1] = { - [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, - [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, - [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, - [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, - [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, - [IPSET_ATTR_NETMASK] = { .type = NLA_U8 }, -}; - static int -hash_ip_create(struct ip_set *set, struct nlattr *head, int len, u32 flags) +hash_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags) { - struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1]; u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; u8 netmask, hbits; struct ip_set_hash *h; @@ -386,10 +356,6 @@ hash_ip_create(struct ip_set *set, struct nlattr *head, int len, u32 flags) pr_debug("Create set %s with family %s\n", set->name, set->family == AF_INET ? "inet" : "inet6"); - if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len, - hash_ip_create_policy)) - return -IPSET_ERR_PROTOCOL; - if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) || !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) || !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) @@ -425,8 +391,7 @@ hash_ip_create(struct ip_set *set, struct nlattr *head, int len, u32 flags) hbits = htable_bits(hashsize); h->table = ip_set_alloc( sizeof(struct htable) - + jhash_size(hbits) * sizeof(struct hbucket), - GFP_KERNEL); + + jhash_size(hbits) * sizeof(struct hbucket)); if (!h->table) { kfree(h); return -ENOMEM; @@ -465,6 +430,21 @@ static struct ip_set_type hash_ip_type __read_mostly = { .family = AF_UNSPEC, .revision = 0, .create = hash_ip_create, + .create_policy = { + [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, + [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, + [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, + [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, + [IPSET_ATTR_NETMASK] = { .type = NLA_U8 }, + }, + .adt_policy = { + [IPSET_ATTR_IP] = { .type = NLA_NESTED }, + [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, + [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, + [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, + }, .me = THIS_MODULE, }; diff --git a/extensions/ipset-6/ip_set_hash_ipport.c b/extensions/ipset-6/ip_set_hash_ipport.c index 0ffc9fb..a2530e6 100644 --- a/extensions/ipset-6/ip_set_hash_ipport.c +++ b/extensions/ipset-6/ip_set_hash_ipport.c @@ -12,9 +12,6 @@ #include #include #include -#include -#include -#include #include #include #include @@ -144,34 +141,17 @@ hash_ipport4_kadt(struct ip_set *set, const struct sk_buff *skb, return adtfn(set, &data, h->timeout); } -static const struct nla_policy -hash_ipport_adt_policy[IPSET_ATTR_ADT_MAX + 1] = { - [IPSET_ATTR_IP] = { .type = NLA_NESTED }, - [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, - [IPSET_ATTR_PORT] = { .type = NLA_U16 }, - [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 }, - [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, - [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, - [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, - [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, -}; - static int -hash_ipport4_uadt(struct ip_set *set, struct nlattr *head, int len, +hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt, u32 *lineno, u32 flags) { const struct ip_set_hash *h = set->data; - struct nlattr *tb[IPSET_ATTR_ADT_MAX+1]; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_ipport4_elem data = { }; u32 ip, ip_to, p, port, port_to; u32 timeout = h->timeout; int ret; - if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len, - hash_ipport_adt_policy)) - return -IPSET_ERR_PROTOCOL; - if (unlikely(!tb[IPSET_ATTR_IP] || !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || @@ -373,25 +353,22 @@ hash_ipport6_kadt(struct ip_set *set, const struct sk_buff *skb, } static int -hash_ipport6_uadt(struct ip_set *set, struct nlattr *head, int len, +hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt, u32 *lineno, u32 flags) { const struct ip_set_hash *h = set->data; - struct nlattr *tb[IPSET_ATTR_ADT_MAX+1]; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_ipport6_elem data = { }; u32 port, port_to; u32 timeout = h->timeout; int ret; - if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len, - hash_ipport_adt_policy)) - return -IPSET_ERR_PROTOCOL; - if (unlikely(!tb[IPSET_ATTR_IP] || !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || - !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || + tb[IPSET_ATTR_IP_TO] || + tb[IPSET_ATTR_CIDR])) return -IPSET_ERR_PROTOCOL; if (tb[IPSET_ATTR_LINENO]) @@ -456,20 +433,9 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *head, int len, /* Create hash:ip type of sets */ -static const struct nla_policy -hash_ipport_create_policy[IPSET_ATTR_CREATE_MAX+1] = { - [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, - [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, - [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, - [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, - [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, - [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, -}; - static int -hash_ipport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags) +hash_ipport_create(struct ip_set *set, struct nlattr *tb[], u32 flags) { - struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1]; struct ip_set_hash *h; u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; u8 hbits; @@ -477,10 +443,6 @@ hash_ipport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags) if (!(set->family == AF_INET || set->family == AF_INET6)) return -IPSET_ERR_INVALID_FAMILY; - if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len, - hash_ipport_create_policy)) - return -IPSET_ERR_PROTOCOL; - if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) || !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) || !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) @@ -506,8 +468,7 @@ hash_ipport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags) hbits = htable_bits(hashsize); h->table = ip_set_alloc( sizeof(struct htable) - + jhash_size(hbits) * sizeof(struct hbucket), - GFP_KERNEL); + + jhash_size(hbits) * sizeof(struct hbucket)); if (!h->table) { kfree(h); return -ENOMEM; @@ -546,6 +507,24 @@ static struct ip_set_type hash_ipport_type __read_mostly = { .family = AF_UNSPEC, .revision = 0, .create = hash_ipport_create, + .create_policy = { + [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, + [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, + [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, + [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, + [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, + }, + .adt_policy = { + [IPSET_ATTR_IP] = { .type = NLA_NESTED }, + [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, + [IPSET_ATTR_PORT] = { .type = NLA_U16 }, + [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 }, + [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, + [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, + [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, + }, .me = THIS_MODULE, }; diff --git a/extensions/ipset-6/ip_set_hash_ipportip.c b/extensions/ipset-6/ip_set_hash_ipportip.c index 5063775..a6d1797 100644 --- a/extensions/ipset-6/ip_set_hash_ipportip.c +++ b/extensions/ipset-6/ip_set_hash_ipportip.c @@ -12,9 +12,6 @@ #include #include #include -#include -#include -#include #include #include #include @@ -148,35 +145,17 @@ hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb, return adtfn(set, &data, h->timeout); } -static const struct nla_policy -hash_ipportip_adt_policy[IPSET_ATTR_ADT_MAX + 1] = { - [IPSET_ATTR_IP] = { .type = NLA_NESTED }, - [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, - [IPSET_ATTR_IP2] = { .type = NLA_NESTED }, - [IPSET_ATTR_PORT] = { .type = NLA_U16 }, - [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 }, - [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, - [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, - [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, - [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, -}; - static int -hash_ipportip4_uadt(struct ip_set *set, struct nlattr *head, int len, +hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt, u32 *lineno, u32 flags) { const struct ip_set_hash *h = set->data; - struct nlattr *tb[IPSET_ATTR_ADT_MAX+1]; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_ipportip4_elem data = { }; u32 ip, ip_to, p, port, port_to; u32 timeout = h->timeout; int ret; - if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len, - hash_ipportip_adt_policy)) - return -IPSET_ERR_PROTOCOL; - if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || @@ -388,25 +367,22 @@ hash_ipportip6_kadt(struct ip_set *set, const struct sk_buff *skb, } static int -hash_ipportip6_uadt(struct ip_set *set, struct nlattr *head, int len, +hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt, u32 *lineno, u32 flags) { const struct ip_set_hash *h = set->data; - struct nlattr *tb[IPSET_ATTR_ADT_MAX+1]; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_ipportip6_elem data = { }; u32 port, port_to; u32 timeout = h->timeout; int ret; - if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len, - hash_ipportip_adt_policy)) - return -IPSET_ERR_PROTOCOL; - if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || - !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || + tb[IPSET_ATTR_IP_TO] || + tb[IPSET_ATTR_CIDR])) return -IPSET_ERR_PROTOCOL; if (tb[IPSET_ATTR_LINENO]) @@ -475,20 +451,9 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *head, int len, /* Create hash:ip type of sets */ -static const struct nla_policy -hash_ipportip_create_policy[IPSET_ATTR_CREATE_MAX+1] = { - [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, - [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, - [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, - [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, - [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, -}; - static int -hash_ipportip_create(struct ip_set *set, struct nlattr *head, - int len, u32 flags) +hash_ipportip_create(struct ip_set *set, struct nlattr *tb[], u32 flags) { - struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1]; struct ip_set_hash *h; u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; u8 hbits; @@ -496,10 +461,6 @@ hash_ipportip_create(struct ip_set *set, struct nlattr *head, if (!(set->family == AF_INET || set->family == AF_INET6)) return -IPSET_ERR_INVALID_FAMILY; - if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len, - hash_ipportip_create_policy)) - return -IPSET_ERR_PROTOCOL; - if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) || !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) || !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) @@ -525,8 +486,7 @@ hash_ipportip_create(struct ip_set *set, struct nlattr *head, hbits = htable_bits(hashsize); h->table = ip_set_alloc( sizeof(struct htable) - + jhash_size(hbits) * sizeof(struct hbucket), - GFP_KERNEL); + + jhash_size(hbits) * sizeof(struct hbucket)); if (!h->table) { kfree(h); return -ENOMEM; @@ -565,6 +525,24 @@ static struct ip_set_type hash_ipportip_type __read_mostly = { .family = AF_UNSPEC, .revision = 0, .create = hash_ipportip_create, + .create_policy = { + [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, + [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, + [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, + [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, + }, + .adt_policy = { + [IPSET_ATTR_IP] = { .type = NLA_NESTED }, + [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, + [IPSET_ATTR_IP2] = { .type = NLA_NESTED }, + [IPSET_ATTR_PORT] = { .type = NLA_U16 }, + [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 }, + [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, + [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, + [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, + }, .me = THIS_MODULE, }; diff --git a/extensions/ipset-6/ip_set_hash_ipportnet.c b/extensions/ipset-6/ip_set_hash_ipportnet.c index 85fa6c7..258eeb9 100644 --- a/extensions/ipset-6/ip_set_hash_ipportnet.c +++ b/extensions/ipset-6/ip_set_hash_ipportnet.c @@ -12,9 +12,6 @@ #include #include #include -#include -#include -#include #include #include #include @@ -168,36 +165,17 @@ hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb, return adtfn(set, &data, h->timeout); } -static const struct nla_policy -hash_ipportnet_adt_policy[IPSET_ATTR_ADT_MAX + 1] = { - [IPSET_ATTR_IP] = { .type = NLA_NESTED }, - [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, - [IPSET_ATTR_IP2] = { .type = NLA_NESTED }, - [IPSET_ATTR_PORT] = { .type = NLA_U16 }, - [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 }, - [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, - [IPSET_ATTR_CIDR2] = { .type = NLA_U8 }, - [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, - [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, - [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, -}; - static int -hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *head, int len, +hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt, u32 *lineno, u32 flags) { const struct ip_set_hash *h = set->data; - struct nlattr *tb[IPSET_ATTR_ADT_MAX+1]; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_ipportnet4_elem data = { .cidr = HOST_MASK }; u32 ip, ip_to, p, port, port_to; u32 timeout = h->timeout; int ret; - if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len, - hash_ipportnet_adt_policy)) - return -IPSET_ERR_PROTOCOL; - if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || @@ -443,25 +421,22 @@ hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb, } static int -hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *head, int len, +hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt, u32 *lineno, u32 flags) { const struct ip_set_hash *h = set->data; - struct nlattr *tb[IPSET_ATTR_ADT_MAX+1]; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_ipportnet6_elem data = { .cidr = HOST_MASK }; u32 port, port_to; u32 timeout = h->timeout; int ret; - if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len, - hash_ipportnet_adt_policy)) - return -IPSET_ERR_PROTOCOL; - if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || - !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) + !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || + tb[IPSET_ATTR_IP_TO] || + tb[IPSET_ATTR_CIDR])) return -IPSET_ERR_PROTOCOL; if (tb[IPSET_ATTR_LINENO]) @@ -538,20 +513,9 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *head, int len, /* Create hash:ip type of sets */ -static const struct nla_policy -hash_ipportnet_create_policy[IPSET_ATTR_CREATE_MAX+1] = { - [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, - [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, - [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, - [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, - [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, -}; - static int -hash_ipportnet_create(struct ip_set *set, struct nlattr *head, - int len, u32 flags) +hash_ipportnet_create(struct ip_set *set, struct nlattr *tb[], u32 flags) { - struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1]; struct ip_set_hash *h; u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; u8 hbits; @@ -559,10 +523,6 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *head, if (!(set->family == AF_INET || set->family == AF_INET6)) return -IPSET_ERR_INVALID_FAMILY; - if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len, - hash_ipportnet_create_policy)) - return -IPSET_ERR_PROTOCOL; - if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) || !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) || !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) @@ -590,8 +550,7 @@ hash_ipportnet_create(struct ip_set *set, struct nlattr *head, hbits = htable_bits(hashsize); h->table = ip_set_alloc( sizeof(struct htable) - + jhash_size(hbits) * sizeof(struct hbucket), - GFP_KERNEL); + + jhash_size(hbits) * sizeof(struct hbucket)); if (!h->table) { kfree(h); return -ENOMEM; @@ -631,6 +590,25 @@ static struct ip_set_type hash_ipportnet_type __read_mostly = { .family = AF_UNSPEC, .revision = 0, .create = hash_ipportnet_create, + .create_policy = { + [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, + [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, + [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, + [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, + }, + .adt_policy = { + [IPSET_ATTR_IP] = { .type = NLA_NESTED }, + [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, + [IPSET_ATTR_IP2] = { .type = NLA_NESTED }, + [IPSET_ATTR_PORT] = { .type = NLA_U16 }, + [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 }, + [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, + [IPSET_ATTR_CIDR2] = { .type = NLA_U8 }, + [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, + [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, + }, .me = THIS_MODULE, }; diff --git a/extensions/ipset-6/ip_set_hash_net.c b/extensions/ipset-6/ip_set_hash_net.c index 7f01112..c5d0722 100644 --- a/extensions/ipset-6/ip_set_hash_net.c +++ b/extensions/ipset-6/ip_set_hash_net.c @@ -12,9 +12,6 @@ #include #include #include -#include -#include -#include #include #include #include @@ -147,27 +144,16 @@ hash_net4_kadt(struct ip_set *set, const struct sk_buff *skb, return adtfn(set, &data, h->timeout); } -static const struct nla_policy hash_net_adt_policy[IPSET_ATTR_ADT_MAX + 1] = { - [IPSET_ATTR_IP] = { .type = NLA_NESTED }, - [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, - [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, -}; - static int -hash_net4_uadt(struct ip_set *set, struct nlattr *head, int len, +hash_net4_uadt(struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt, u32 *lineno, u32 flags) { const struct ip_set_hash *h = set->data; - struct nlattr *tb[IPSET_ATTR_ADT_MAX+1]; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_net4_elem data = { .cidr = HOST_MASK }; u32 timeout = h->timeout; int ret; - if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len, - hash_net_adt_policy)) - return -IPSET_ERR_PROTOCOL; - if (unlikely(!tb[IPSET_ATTR_IP] || !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) return -IPSET_ERR_PROTOCOL; @@ -324,20 +310,15 @@ hash_net6_kadt(struct ip_set *set, const struct sk_buff *skb, } static int -hash_net6_uadt(struct ip_set *set, struct nlattr *head, int len, +hash_net6_uadt(struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt, u32 *lineno, u32 flags) { const struct ip_set_hash *h = set->data; - struct nlattr *tb[IPSET_ATTR_ADT_MAX+1]; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_net6_elem data = { .cidr = HOST_MASK }; u32 timeout = h->timeout; int ret; - if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len, - hash_net_adt_policy)) - return -IPSET_ERR_PROTOCOL; - if (unlikely(!tb[IPSET_ATTR_IP] || !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) return -IPSET_ERR_PROTOCOL; @@ -370,19 +351,9 @@ hash_net6_uadt(struct ip_set *set, struct nlattr *head, int len, /* Create hash:ip type of sets */ -static const struct nla_policy -hash_net_create_policy[IPSET_ATTR_CREATE_MAX+1] = { - [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, - [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, - [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, - [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, - [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, -}; - static int -hash_net_create(struct ip_set *set, struct nlattr *head, int len, u32 flags) +hash_net_create(struct ip_set *set, struct nlattr *tb[], u32 flags) { - struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1]; u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; struct ip_set_hash *h; u8 hbits; @@ -390,10 +361,6 @@ hash_net_create(struct ip_set *set, struct nlattr *head, int len, u32 flags) if (!(set->family == AF_INET || set->family == AF_INET6)) return -IPSET_ERR_INVALID_FAMILY; - if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len, - hash_net_create_policy)) - return -IPSET_ERR_PROTOCOL; - if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) || !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) || !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) @@ -421,8 +388,7 @@ hash_net_create(struct ip_set *set, struct nlattr *head, int len, u32 flags) hbits = htable_bits(hashsize); h->table = ip_set_alloc( sizeof(struct htable) - + jhash_size(hbits) * sizeof(struct hbucket), - GFP_KERNEL); + + jhash_size(hbits) * sizeof(struct hbucket)); if (!h->table) { kfree(h); return -ENOMEM; @@ -461,6 +427,18 @@ static struct ip_set_type hash_net_type __read_mostly = { .family = AF_UNSPEC, .revision = 0, .create = hash_net_create, + .create_policy = { + [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, + [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, + [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, + [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, + }, + .adt_policy = { + [IPSET_ATTR_IP] = { .type = NLA_NESTED }, + [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, + }, .me = THIS_MODULE, }; diff --git a/extensions/ipset-6/ip_set_hash_netport.c b/extensions/ipset-6/ip_set_hash_netport.c index 6e86b62..249c5b3 100644 --- a/extensions/ipset-6/ip_set_hash_netport.c +++ b/extensions/ipset-6/ip_set_hash_netport.c @@ -12,9 +12,6 @@ #include #include #include -#include -#include -#include #include #include #include @@ -164,33 +161,17 @@ hash_netport4_kadt(struct ip_set *set, const struct sk_buff *skb, return adtfn(set, &data, h->timeout); } -static const struct nla_policy -hash_netport_adt_policy[IPSET_ATTR_ADT_MAX + 1] = { - [IPSET_ATTR_IP] = { .type = NLA_NESTED }, - [IPSET_ATTR_PORT] = { .type = NLA_U16 }, - [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 }, - [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, - [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, - [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, - [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, -}; - static int -hash_netport4_uadt(struct ip_set *set, struct nlattr *head, int len, +hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt, u32 *lineno, u32 flags) { const struct ip_set_hash *h = set->data; - struct nlattr *tb[IPSET_ATTR_ADT_MAX+1]; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_netport4_elem data = { .cidr = HOST_MASK }; u32 port, port_to; u32 timeout = h->timeout; int ret; - if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len, - hash_netport_adt_policy)) - return -IPSET_ERR_PROTOCOL; - if (unlikely(!tb[IPSET_ATTR_IP] || !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || @@ -401,21 +382,16 @@ hash_netport6_kadt(struct ip_set *set, const struct sk_buff *skb, } static int -hash_netport6_uadt(struct ip_set *set, struct nlattr *head, int len, +hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt, u32 *lineno, u32 flags) { const struct ip_set_hash *h = set->data; - struct nlattr *tb[IPSET_ATTR_ADT_MAX+1]; ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_netport6_elem data = { .cidr = HOST_MASK }; u32 port, port_to; u32 timeout = h->timeout; int ret; - if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len, - hash_netport_adt_policy)) - return -IPSET_ERR_PROTOCOL; - if (unlikely(!tb[IPSET_ATTR_IP] || !ip_set_attr_netorder(tb, IPSET_ATTR_PORT) || !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || @@ -490,20 +466,9 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *head, int len, /* Create hash:ip type of sets */ -static const struct nla_policy -hash_netport_create_policy[IPSET_ATTR_CREATE_MAX+1] = { - [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, - [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, - [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, - [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, - [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, - [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, -}; - static int -hash_netport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags) +hash_netport_create(struct ip_set *set, struct nlattr *tb[], u32 flags) { - struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1]; struct ip_set_hash *h; u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; u8 hbits; @@ -511,10 +476,6 @@ hash_netport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags) if (!(set->family == AF_INET || set->family == AF_INET6)) return -IPSET_ERR_INVALID_FAMILY; - if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len, - hash_netport_create_policy)) - return -IPSET_ERR_PROTOCOL; - if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) || !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) || !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) @@ -542,8 +503,7 @@ hash_netport_create(struct ip_set *set, struct nlattr *head, int len, u32 flags) hbits = htable_bits(hashsize); h->table = ip_set_alloc( sizeof(struct htable) - + jhash_size(hbits) * sizeof(struct hbucket), - GFP_KERNEL); + + jhash_size(hbits) * sizeof(struct hbucket)); if (!h->table) { kfree(h); return -ENOMEM; @@ -582,6 +542,23 @@ static struct ip_set_type hash_netport_type __read_mostly = { .family = AF_UNSPEC, .revision = 0, .create = hash_netport_create, + .create_policy = { + [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, + [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, + [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, + [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, + [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, + }, + .adt_policy = { + [IPSET_ATTR_IP] = { .type = NLA_NESTED }, + [IPSET_ATTR_PORT] = { .type = NLA_U16 }, + [IPSET_ATTR_PORT_TO] = { .type = NLA_U16 }, + [IPSET_ATTR_PROTO] = { .type = NLA_U8 }, + [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, + [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, + }, .me = THIS_MODULE, }; diff --git a/extensions/ipset-6/ip_set_list_set.c b/extensions/ipset-6/ip_set_list_set.c index 398adc4..7fc98ff 100644 --- a/extensions/ipset-6/ip_set_list_set.c +++ b/extensions/ipset-6/ip_set_list_set.c @@ -111,16 +111,6 @@ list_set_kadt(struct ip_set *set, const struct sk_buff *skb, return -EINVAL; } -static const struct nla_policy list_set_adt_policy[IPSET_ATTR_ADT_MAX+1] = { - [IPSET_ATTR_NAME] = { .type = NLA_STRING, - .len = IPSET_MAXNAMELEN }, - [IPSET_ATTR_NAMEREF] = { .type = NLA_STRING, - .len = IPSET_MAXNAMELEN }, - [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, - [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, - [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, -}; - static bool next_id_eq(const struct list_set *map, u32 i, ip_set_id_t id) { @@ -204,11 +194,10 @@ list_set_del(struct list_set *map, ip_set_id_t id, u32 i) } static int -list_set_uadt(struct ip_set *set, struct nlattr *head, int len, +list_set_uadt(struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt, u32 *lineno, u32 flags) { struct list_set *map = set->data; - struct nlattr *tb[IPSET_ATTR_ADT_MAX+1]; bool with_timeout = with_timeout(map->timeout); int before = 0; u32 timeout = map->timeout; @@ -218,10 +207,6 @@ list_set_uadt(struct ip_set *set, struct nlattr *head, int len, u32 i; int ret = 0; - if (nla_parse(tb, IPSET_ATTR_ADT_MAX, head, len, - list_set_adt_policy)) - return -IPSET_ERR_PROTOCOL; - if (unlikely(!tb[IPSET_ATTR_NAME] || !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS))) @@ -392,7 +377,7 @@ list_set_head(struct ip_set *set, struct sk_buff *skb) return 0; nla_put_failure: - return -EFAULT; + return -EMSGSIZE; } static int @@ -406,7 +391,7 @@ list_set_list(const struct ip_set *set, atd = ipset_nest_start(skb, IPSET_ATTR_ADT); if (!atd) - return -EFAULT; + return -EMSGSIZE; for (; cb->args[2] < map->size; cb->args[2]++) { i = cb->args[2]; e = list_set_elem(map, i); @@ -418,7 +403,7 @@ list_set_list(const struct ip_set *set, if (!nested) { if (i == first) { nla_nest_cancel(skb, atd); - return -EFAULT; + return -EMSGSIZE; } else goto nla_put_failure; } @@ -441,6 +426,10 @@ finish: nla_put_failure: nla_nest_cancel(skb, nested); ipset_nest_end(skb, atd); + if (unlikely(i == first)) { + cb->args[2] = 0; + return -EMSGSIZE; + } return 0; } @@ -501,12 +490,6 @@ list_set_gc_init(struct ip_set *set) /* Create list:set type of sets */ -static const struct nla_policy -list_set_create_policy[IPSET_ATTR_CREATE_MAX+1] = { - [IPSET_ATTR_SIZE] = { .type = NLA_U32 }, - [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, -}; - static bool init_list_set(struct ip_set *set, u32 size, size_t dsize, unsigned long timeout) @@ -533,16 +516,10 @@ init_list_set(struct ip_set *set, u32 size, size_t dsize, } static int -list_set_create(struct ip_set *set, struct nlattr *head, int len, - u32 flags) +list_set_create(struct ip_set *set, struct nlattr *tb[], u32 flags) { - struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1]; u32 size = IP_SET_LIST_DEFAULT_SIZE; - if (nla_parse(tb, IPSET_ATTR_CREATE_MAX, head, len, - list_set_create_policy)) - return -IPSET_ERR_PROTOCOL; - if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_SIZE) || !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT))) return -IPSET_ERR_PROTOCOL; @@ -575,6 +552,19 @@ static struct ip_set_type list_set_type __read_mostly = { .family = AF_UNSPEC, .revision = 0, .create = list_set_create, + .create_policy = { + [IPSET_ATTR_SIZE] = { .type = NLA_U32 }, + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, + }, + .adt_policy = { + [IPSET_ATTR_NAME] = { .type = NLA_STRING, + .len = IPSET_MAXNAMELEN }, + [IPSET_ATTR_NAMEREF] = { .type = NLA_STRING, + .len = IPSET_MAXNAMELEN }, + [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, + [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, + [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, + }, .me = THIS_MODULE, }; diff --git a/extensions/ipset-6/libipset/mnl.c b/extensions/ipset-6/libipset/mnl.c index 9d1b630..91a5ee4 100644 --- a/extensions/ipset-6/libipset/mnl.c +++ b/extensions/ipset-6/libipset/mnl.c @@ -43,8 +43,8 @@ static const uint16_t cmdflags[] = { [IPSET_CMD_FLUSH-1] = NLM_F_REQUEST|NLM_F_ACK, [IPSET_CMD_RENAME-1] = NLM_F_REQUEST|NLM_F_ACK, [IPSET_CMD_SWAP-1] = NLM_F_REQUEST|NLM_F_ACK, - [IPSET_CMD_LIST-1] = NLM_F_REQUEST, - [IPSET_CMD_SAVE-1] = NLM_F_REQUEST, + [IPSET_CMD_LIST-1] = NLM_F_REQUEST|NLM_F_ACK, + [IPSET_CMD_SAVE-1] = NLM_F_REQUEST|NLM_F_ACK, [IPSET_CMD_ADD-1] = NLM_F_REQUEST|NLM_F_ACK|NLM_F_EXCL, [IPSET_CMD_DEL-1] = NLM_F_REQUEST|NLM_F_ACK|NLM_F_EXCL, [IPSET_CMD_TEST-1] = NLM_F_REQUEST|NLM_F_ACK, @@ -83,7 +83,7 @@ ipset_mnl_fill_hdr(struct ipset_handle *handle, enum ipset_cmd cmd, nlh->nlmsg_flags = NLM_F_REQUEST; if (cmdflags[cmd-1] & NLM_F_ACK) nlh->nlmsg_flags |= NLM_F_ACK; - nlh->nlmsg_seq = handle->seq = time(NULL); + nlh->nlmsg_seq = ++handle->seq; ghdr = mnl_nlmsg_put_extra_header(nlh, sizeof(struct genlmsghdr)); ghdr->cmd = cmd; @@ -225,6 +225,7 @@ ipset_mnl_init(mnl_cb_t *cb_ctl, void *data) handle->portid = mnl_socket_get_portid(handle->h); handle->cb_ctl = cb_ctl; handle->data = data; + handle->seq = time(NULL); if (ipset_mnl_getid(handle, false) < 0) goto close_nl; diff --git a/extensions/ipset-6/libipset/parse.c b/extensions/ipset-6/libipset/parse.c index e998df5..cd1ad32 100644 --- a/extensions/ipset-6/libipset/parse.c +++ b/extensions/ipset-6/libipset/parse.c @@ -1416,15 +1416,14 @@ ipset_parse_ignored(struct ipset_session *session, */ int ipset_call_parser(struct ipset_session *session, - ipset_parsefn parse, const char *optstr, - enum ipset_opt opt, const char *str) + const struct ipset_arg *arg, + const char *str) { if (ipset_data_flags_test(ipset_session_data(session), - IPSET_FLAG(opt))) - syntax_err("%s already specified", optstr); + IPSET_FLAG(arg->opt))) + syntax_err("%s already specified", arg->name[0]); - return parse(session, opt, parse == ipset_parse_ignored - ? optstr : str); + return arg->parse(session, arg->opt, str); } #define parse_elem(s, t, d, str) \ diff --git a/extensions/ipset-6/libipset/print.c b/extensions/ipset-6/libipset/print.c index 7ec786f..5284b0a 100644 --- a/extensions/ipset-6/libipset/print.c +++ b/extensions/ipset-6/libipset/print.c @@ -158,7 +158,8 @@ __getnameinfo##f(char *buf, unsigned int len, \ sizeof(saddr), \ buf, len, NULL, 0, flags); \ \ - if (err == EAI_AGAIN && !(flags & NI_NUMERICHOST)) \ + if (!(flags & NI_NUMERICHOST) && \ + (err == EAI_AGAIN || (err == 0 && strchr(buf, '-') != NULL))) \ err = getnameinfo((const struct sockaddr *)&saddr, \ sizeof(saddr), \ buf, len, NULL, 0, \ @@ -229,7 +230,7 @@ ipset_print_ip(char *buf, unsigned int len, D("CIDR: %u", cidr); } else cidr = family == AF_INET6 ? 128 : 32; - flags = env & (1 << IPSET_ENV_RESOLVE) ? 0 : NI_NUMERICHOST; + flags = (env & IPSET_ENV_RESOLVE) ? 0 : NI_NUMERICHOST; ip = ipset_data_get(data, opt); assert(ip); @@ -296,7 +297,7 @@ ipset_print_ipaddr(char *buf, unsigned int len, cidr = *(const uint8_t *) ipset_data_get(data, cidropt); else cidr = family == AF_INET6 ? 128 : 32; - flags = env & (1 << IPSET_ENV_RESOLVE) ? 0 : NI_NUMERICHOST; + flags = (env & IPSET_ENV_RESOLVE) ? 0 : NI_NUMERICHOST; ip = ipset_data_get(data, opt); assert(ip); diff --git a/extensions/ipset-6/libipset/types.c b/extensions/ipset-6/libipset/types.c index 69dac6a..5eb53c4 100644 --- a/extensions/ipset-6/libipset/types.c +++ b/extensions/ipset-6/libipset/types.c @@ -441,13 +441,15 @@ ipset_type_add(struct ipset_type *type) assert(type); + if (strlen(type->name) > IPSET_MAXNAMELEN - 1) + return -EINVAL; + /* Add to the list: higher revision numbers first */ for (t = typelist, prev = NULL; t != NULL; t = t->next) { if (STREQ(t->name, type->name)) { - if (t->revision == type->revision) { - errno = EEXIST; - return -1; - } else if (t->revision < type->revision) { + if (t->revision == type->revision) + return -EEXIST; + else if (t->revision < type->revision) { type->next = t; if (prev) prev->next = type; @@ -457,10 +459,9 @@ ipset_type_add(struct ipset_type *type) } } if (t->next != NULL && STREQ(t->next->name, type->name)) { - if (t->next->revision == type->revision) { - errno = EEXIST; - return -1; - } else if (t->next->revision < type->revision) { + if (t->next->revision == type->revision) + return -EEXIST; + else if (t->next->revision < type->revision) { type->next = t->next; t->next = type; return 0; diff --git a/extensions/ipset-6/src/errcode.c b/extensions/ipset-6/src/errcode.c index 313c500..6370ec7 100644 --- a/extensions/ipset-6/src/errcode.c +++ b/extensions/ipset-6/src/errcode.c @@ -21,8 +21,10 @@ /* Core kernel error codes */ static const struct ipset_errcode_table core_errcode_table[] = { /* Generic error codes */ - { EEXIST, 0, + { ENOENT, 0, "The set with the given name does not exist" }, + { EMSGSIZE, 0, + "Kernel error received: message could not be created" }, { IPSET_ERR_PROTOCOL, 0, "Kernel error received: ipset protocol error" }, @@ -30,14 +32,14 @@ static const struct ipset_errcode_table core_errcode_table[] = { { EEXIST, IPSET_CMD_CREATE, "Set cannot be created: set with the same name already exists" }, { IPSET_ERR_FIND_TYPE, 0, - "Kernel error received: set type does not supported" }, + "Kernel error received: set type not supported" }, { IPSET_ERR_MAX_SETS, 0, "Kernel error received: maximal number of sets reached, " "cannot create more." }, { IPSET_ERR_INVALID_NETMASK, 0, "The value of the netmask parameter is invalid" }, { IPSET_ERR_INVALID_FAMILY, 0, - "The protocol family not supported by the set type" }, + "Protocol family not supported by the set type" }, /* DESTROY specific error codes */ { IPSET_ERR_BUSY, IPSET_CMD_DESTROY, diff --git a/extensions/ipset-6/src/ipset.c b/extensions/ipset-6/src/ipset.c index 8ed3e10..05f8ef3 100644 --- a/extensions/ipset-6/src/ipset.c +++ b/extensions/ipset-6/src/ipset.c @@ -206,62 +206,54 @@ restore(char *argv0) static int call_parser(int *argc, char *argv[], const struct ipset_arg *args) { - int i = 1, ret = 0; + int ret = 0; const struct ipset_arg *arg; const char *optstr; /* Currently CREATE and ADT may have got additional arguments */ - if (!args) - goto done; - for (arg = args; arg->opt; arg++) { - for (i = 1; i < *argc; ) { - D("argc: %u, i: %u: %s vs %s", - *argc, i, argv[i], arg->name[0]); - if (!(ipset_match_option(argv[i], arg->name))) { - i++; + if (!args && *argc > 1) + goto err_unknown; + while (*argc > 1) { + for (arg = args; arg->opt; arg++) { + D("argc: %u, %s vs %s", *argc, argv[1], arg->name[0]); + if (!(ipset_match_option(argv[1], arg->name))) continue; - } - optstr = argv[i]; + + optstr = argv[1]; /* Shift off matched option */ D("match %s", arg->name[0]); - ipset_shift_argv(argc, argv, i); - D("argc: %u, i: %u", *argc, i); + ipset_shift_argv(argc, argv, 1); switch (arg->has_arg) { case IPSET_MANDATORY_ARG: - if (i + 1 > *argc) + if (*argc < 2) return exit_error(PARAMETER_PROBLEM, "Missing mandatory argument " "of option `%s'", arg->name[0]); /* Fall through */ case IPSET_OPTIONAL_ARG: - if (i + 1 <= *argc) { - ret = ipset_call_parser(session, - arg->parse, - optstr, arg->opt, - argv[i]); + if (*argc >= 2) { + ret = ipset_call_parser(session, arg, argv[1]); if (ret < 0) return ret; - ipset_shift_argv(argc, argv, i); + ipset_shift_argv(argc, argv, 1); break; } /* Fall through */ default: - ret = ipset_call_parser(session, - arg->parse, - optstr, arg->opt, - optstr); + ret = ipset_call_parser(session, arg, optstr); if (ret < 0) return ret; } + break; } + if (!arg->opt) + goto err_unknown; } -done: - if (i < *argc) - return exit_error(PARAMETER_PROBLEM, - "Unknown argument: `%s'", - argv[i]); return ret; + +err_unknown: + return exit_error(PARAMETER_PROBLEM, "Unknown argument: `%s'", argv[1]); } static enum ipset_adt @@ -476,61 +468,57 @@ parse_commandline(int argc, char *argv[]) /* Second: parse command */ for (command = ipset_commands; - command->cmd && cmd == IPSET_CMD_NONE; + argc > 1 && command->cmd && cmd == IPSET_CMD_NONE; command++) { - for (i = 1; i < argc; ) { - if (!ipset_match_cmd(argv[1], command->name)) { - i++; - continue; - } - if (restore_line != 0 - && (command->cmd == IPSET_CMD_RESTORE - || command->cmd == IPSET_CMD_VERSION - || command->cmd == IPSET_CMD_HELP)) - return exit_error(PARAMETER_PROBLEM, - "Command `%s' is invalid " - "in restore mode.", - command->name[0]); - if (interactive - && command->cmd == IPSET_CMD_RESTORE) { - printf("Restore command ignored " - "in interactive mode\n"); - return 0; - } + if (!ipset_match_cmd(argv[1], command->name)) + continue; - /* Shift off matched command arg */ - ipset_shift_argv(&argc, argv, i); - cmd = command->cmd; - switch (command->has_arg) { - case IPSET_MANDATORY_ARG: - case IPSET_MANDATORY_ARG2: - if (i + 1 > argc) - return exit_error(PARAMETER_PROBLEM, - "Missing mandatory argument " - "to command %s", - command->name[0]); - /* Fall through */ - case IPSET_OPTIONAL_ARG: - arg0 = argv[i]; - if (i + 1 <= argc) - /* Shift off first arg */ - ipset_shift_argv(&argc, argv, i); - break; - default: - break; - } - if (command->has_arg == IPSET_MANDATORY_ARG2) { - if (i + 1 > argc) - return exit_error(PARAMETER_PROBLEM, - "Missing second mandatory " - "argument to command %s", - command->name[0]); - arg1 = argv[i]; - /* Shift off second arg */ - ipset_shift_argv(&argc, argv, i); - } + if (restore_line != 0 + && (command->cmd == IPSET_CMD_RESTORE + || command->cmd == IPSET_CMD_VERSION + || command->cmd == IPSET_CMD_HELP)) + return exit_error(PARAMETER_PROBLEM, + "Command `%s' is invalid " + "in restore mode.", + command->name[0]); + if (interactive && command->cmd == IPSET_CMD_RESTORE) { + printf("Restore command ignored " + "in interactive mode\n"); + return 0; + } + + /* Shift off matched command arg */ + ipset_shift_argv(&argc, argv, 1); + cmd = command->cmd; + switch (command->has_arg) { + case IPSET_MANDATORY_ARG: + case IPSET_MANDATORY_ARG2: + if (argc < 2) + return exit_error(PARAMETER_PROBLEM, + "Missing mandatory argument " + "to command %s", + command->name[0]); + /* Fall through */ + case IPSET_OPTIONAL_ARG: + arg0 = argv[1]; + if (argc >= 2) + /* Shift off first arg */ + ipset_shift_argv(&argc, argv, 1); + break; + default: break; } + if (command->has_arg == IPSET_MANDATORY_ARG2) { + if (argc < 2) + return exit_error(PARAMETER_PROBLEM, + "Missing second mandatory " + "argument to command %s", + command->name[0]); + arg1 = argv[1]; + /* Shift off second arg */ + ipset_shift_argv(&argc, argv, 1); + } + break; } /* Third: catch interactive mode, handle help, version */ @@ -565,7 +553,8 @@ parse_commandline(int argc, char *argv[]) argv[1]); return exit_error(PARAMETER_PROBLEM, "No command specified."); case IPSET_CMD_VERSION: - printf("%s v%s.\n", program_name, program_version); + printf("%s v%s, protocol version: %u\n", + program_name, program_version, IPSET_PROTOCOL); if (interactive) return 0; return exit_error(NO_PROBLEM, NULL); diff --git a/extensions/ipset-6/src/ui.c b/extensions/ipset-6/src/ui.c index 176e1b2..3601c65 100644 --- a/extensions/ipset-6/src/ui.c +++ b/extensions/ipset-6/src/ui.c @@ -23,9 +23,9 @@ const struct ipset_commands ipset_commands[] = { /* Order is important */ - { /* c[reate], --create, n, -N */ + { /* c[reate], --create, n[ew], -N */ .cmd = IPSET_CMD_CREATE, - .name = { "create", "n" }, + .name = { "create", "new" }, .has_arg = IPSET_MANDATORY_ARG2, .help = "SETNAME TYPENAME [type-specific-options]\n" " Create a new set", @@ -143,14 +143,14 @@ ipset_match_cmd(const char *arg, const char * const name[]) if (len > strlen(name[0]) || !len) return false; - else if (strncmp(arg, name[0], len) == 0) + else if (len > 1 && + ((strncmp(arg, name[0], len) == 0) || + (name[1] != NULL && (strncmp(arg, name[1], len) == 0)))) return true; else if (len != 1) return false; - else if (name[1] == NULL) - return tolower(arg[0]) == name[0][0]; - else - return tolower(arg[0]) == name[1][0]; + else return tolower(arg[0]) == name[0][0] || + (name[1] != NULL && tolower(arg[0]) == name[1][0]); } const struct ipset_envopts ipset_envopts[] = { diff --git a/extensions/ipset-6/xt_set.c b/extensions/ipset-6/xt_set.c index 56e6937..f2a9088 100644 --- a/extensions/ipset-6/xt_set.c +++ b/extensions/ipset-6/xt_set.c @@ -56,10 +56,10 @@ match_set(ip_set_id_t index, const struct sk_buff *skb, #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) #define CHECK_OK 1 -#define CHECK_FAIL 0 +#define CHECK_FAIL(err) 0 #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35) */ #define CHECK_OK 0 -#define CHECK_FAIL (-EINVAL) +#define CHECK_FAIL(err) (err) #endif #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35) @@ -110,11 +110,12 @@ set_match_v0_checkentry(const struct xt_mtchk_param *par) if (index == IPSET_INVALID_ID) { pr_warning("Cannot find set indentified by id %u to match\n", info->match_set.index); - return CHECK_FAIL; /* error */ + return CHECK_FAIL(-ENOENT); /* error */ } if (info->match_set.u.flags[IPSET_DIM_MAX-1] != 0) { - pr_warning("That's nasty!\n"); - return CHECK_FAIL; /* error */ + pr_warning("Protocol error: set match dimension " + "is over the limit!\n"); + return CHECK_FAIL(-ERANGE); /* error */ } /* Fill out compatibility data */ @@ -167,24 +168,25 @@ set_target_v0_checkentry(const struct xt_tgchk_param *par) if (info->add_set.index != IPSET_INVALID_ID) { index = ip_set_nfnl_get_byindex(info->add_set.index); if (index == IPSET_INVALID_ID) { - pr_warning("cannot find add_set index %u as target\n", + pr_warning("Cannot find add_set index %u as target\n", info->add_set.index); - return CHECK_FAIL; /* error */ + return CHECK_FAIL(-ENOENT); /* error */ } } if (info->del_set.index != IPSET_INVALID_ID) { index = ip_set_nfnl_get_byindex(info->del_set.index); if (index == IPSET_INVALID_ID) { - pr_warning("cannot find del_set index %u as target\n", + pr_warning("Cannot find del_set index %u as target\n", info->del_set.index); - return CHECK_FAIL; /* error */ + return CHECK_FAIL(-ENOENT); /* error */ } } if (info->add_set.u.flags[IPSET_DIM_MAX-1] != 0 || info->del_set.u.flags[IPSET_DIM_MAX-1] != 0) { - pr_warning("That's nasty!\n"); - return CHECK_FAIL; /* error */ + pr_warning("Protocol error: SET target dimension " + "is over the limit!\n"); + return CHECK_FAIL(-ERANGE); /* error */ } /* Fill out compatibility data */ @@ -239,11 +241,12 @@ set_match_checkentry(const struct xt_mtchk_param *par) if (index == IPSET_INVALID_ID) { pr_warning("Cannot find set indentified by id %u to match\n", info->match_set.index); - return CHECK_FAIL; /* error */ + return CHECK_FAIL(-ENOENT); /* error */ } if (info->match_set.dim > IPSET_DIM_MAX) { - pr_warning("That's nasty!\n"); - return CHECK_FAIL; /* error */ + pr_warning("Protocol error: set match dimension " + "is over the limit!\n"); + return CHECK_FAIL(-ERANGE); /* error */ } return CHECK_OK; @@ -295,24 +298,25 @@ set_target_checkentry(const struct xt_tgchk_param *par) if (info->add_set.index != IPSET_INVALID_ID) { index = ip_set_nfnl_get_byindex(info->add_set.index); if (index == IPSET_INVALID_ID) { - pr_warning("cannot find add_set index %u as target\n", + pr_warning("Cannot find add_set index %u as target\n", info->add_set.index); - return CHECK_FAIL; /* error */ + return CHECK_FAIL(-ENOENT); /* error */ } } if (info->del_set.index != IPSET_INVALID_ID) { index = ip_set_nfnl_get_byindex(info->del_set.index); if (index == IPSET_INVALID_ID) { - pr_warning("cannot find del_set index %u as target\n", + pr_warning("Cannot find del_set index %u as target\n", info->del_set.index); - return CHECK_FAIL; /* error */ + return CHECK_FAIL(-ENOENT); /* error */ } } if (info->add_set.dim > IPSET_DIM_MAX || info->del_set.flags > IPSET_DIM_MAX) { - pr_warning("That's nasty!\n"); - return CHECK_FAIL; /* error */ + pr_warning("Protocol error: SET target dimension " + "is over the limit!\n"); + return CHECK_FAIL(-ERANGE); /* error */ } return CHECK_OK; diff --git a/extensions/ipset-6/xt_set.h b/extensions/ipset-6/xt_set.h index b5450a9..6d6e04f 100644 --- a/extensions/ipset-6/xt_set.h +++ b/extensions/ipset-6/xt_set.h @@ -1,6 +1,7 @@ #ifndef _XT_SET_H #define _XT_SET_H +#include #include "ip_set.h" /* Revision 0 interface: backward compatible with netfilter/iptables */ diff --git a/mconfig b/mconfig index 03c8719..221fcfb 100644 --- a/mconfig +++ b/mconfig @@ -1,30 +1,3 @@ # -*- Makefile -*- # -build_ACCOUNT=m -build_CHAOS=m -build_CHECKSUM= -build_DELUDE=m -build_DHCPMAC=m -build_DNETMAP= -build_ECHO= -build_IPMARK=m -build_LOGMARK=m -build_RAWNAT=m -build_STEAL=m -build_SYSRQ=m -build_TARPIT=m -build_TEE= -build_condition=m -build_fuzzy=m -build_geoip=m -build_gradm=m -build_iface=m -build_ipp2p=m -build_ipset4=m -build_ipset6= -build_ipv4options=m -build_length2=m -build_lscan=m -build_pknock=m -build_psd=m -build_quota2=m +build_ipset6=m From 499c6db75e0897a5d2f6c36142eebf7926a3afb0 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 4 Apr 2011 00:39:50 +0200 Subject: [PATCH 3/4] ipset: update to ipset-6.2 --- doc/changelog.txt | 6 + extensions/ipset-6/ip_set.h | 5 +- extensions/ipset-6/ip_set_ahash.h | 18 +-- extensions/ipset-6/ip_set_bitmap_ip.c | 23 ++- extensions/ipset-6/ip_set_bitmap_ipmac.c | 24 +-- extensions/ipset-6/ip_set_bitmap_port.c | 23 ++- extensions/ipset-6/ip_set_core.c | 134 ++++++++++------- extensions/ipset-6/ip_set_getport.c | 16 +- extensions/ipset-6/ip_set_getport.h | 12 ++ extensions/ipset-6/ip_set_hash_ip.c | 10 +- extensions/ipset-6/ip_set_hash_ipport.c | 48 +++--- extensions/ipset-6/ip_set_hash_ipportip.c | 48 +++--- extensions/ipset-6/ip_set_hash_ipportnet.c | 48 +++--- extensions/ipset-6/ip_set_hash_net.c | 8 +- extensions/ipset-6/ip_set_hash_netport.c | 44 ++---- extensions/ipset-6/ip_set_list_set.c | 137 +++++++++++------- extensions/ipset-6/ipset.8 | 29 ++-- extensions/ipset-6/libipset/parse.c | 5 +- extensions/ipset-6/libipset/print.c | 2 + extensions/ipset-6/libipset/types.c | 33 ++--- extensions/ipset-6/src/ipset_hash_ipport.c | 6 +- extensions/ipset-6/src/ipset_hash_ipportip.c | 6 +- extensions/ipset-6/src/ipset_hash_ipportnet.c | 6 +- extensions/ipset-6/src/ipset_hash_netport.c | 5 +- 24 files changed, 370 insertions(+), 326 deletions(-) diff --git a/doc/changelog.txt b/doc/changelog.txt index 922054b..cf2f0ae 100644 --- a/doc/changelog.txt +++ b/doc/changelog.txt @@ -15,6 +15,12 @@ Enhancements: * check ICMP and ICMPv6 with the set match and target in the testsuite * avoid possible syntax clashing at saving hostnames * fix linking with CONFIG_IPV6=n +- update to ipset 6.1 + * sctp, udplite support for the hash:*port* types + * fix hash:*port* types ignoring the address range for non-{tcp,udp} + * revision reporting fixes +- update to ipset 6.2 + * list:set timeout variant fixes v1.33 (2011-02-02) diff --git a/extensions/ipset-6/ip_set.h b/extensions/ipset-6/ip_set.h index ec1438f..8026f1b 100644 --- a/extensions/ipset-6/ip_set.h +++ b/extensions/ipset-6/ip_set.h @@ -216,7 +216,8 @@ enum ip_set_feature { struct ip_set; -typedef int (*ipset_adtfn)(struct ip_set *set, void *value, u32 timeout); +typedef int (*ipset_adtfn)(struct ip_set *set, void *value, + u32 timeout, u32 flags); /* Set type, variant-specific part */ struct ip_set_type_variant { @@ -295,7 +296,7 @@ struct ip_set { /* Lock protecting the set data */ rwlock_t lock; /* References to the set */ - atomic_t ref; + u32 ref; /* The core set type */ struct ip_set_type *type; /* The type variant doing the real job */ diff --git a/extensions/ipset-6/ip_set_ahash.h b/extensions/ipset-6/ip_set_ahash.h index b6c4c2f..36a5b00 100644 --- a/extensions/ipset-6/ip_set_ahash.h +++ b/extensions/ipset-6/ip_set_ahash.h @@ -349,7 +349,7 @@ retry: /* Add an element to a hash and update the internal counters when succeeded, * otherwise report the proper error code. */ static int -type_pf_add(struct ip_set *set, void *value, u32 timeout) +type_pf_add(struct ip_set *set, void *value, u32 timeout, u32 flags) { struct ip_set_hash *h = set->data; struct htable *t; @@ -388,7 +388,7 @@ out: * and free up space if possible. */ static int -type_pf_del(struct ip_set *set, void *value, u32 timeout) +type_pf_del(struct ip_set *set, void *value, u32 timeout, u32 flags) { struct ip_set_hash *h = set->data; struct htable *t = h->table; @@ -463,7 +463,7 @@ type_pf_test_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout) /* Test whether the element is added to the set */ static int -type_pf_test(struct ip_set *set, void *value, u32 timeout) +type_pf_test(struct ip_set *set, void *value, u32 timeout, u32 flags) { struct ip_set_hash *h = set->data; struct htable *t = h->table; @@ -515,8 +515,7 @@ type_pf_head(struct ip_set *set, struct sk_buff *skb) if (h->netmask != HOST_MASK) NLA_PUT_U8(skb, IPSET_ATTR_NETMASK, h->netmask); #endif - NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, - htonl(atomic_read(&set->ref) - 1)); + NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)); NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, htonl(memsize)); if (with_timeout(h->timeout)) NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(h->timeout)); @@ -777,7 +776,7 @@ retry: } static int -type_pf_tadd(struct ip_set *set, void *value, u32 timeout) +type_pf_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags) { struct ip_set_hash *h = set->data; struct htable *t = h->table; @@ -785,6 +784,7 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout) struct hbucket *n; struct type_pf_elem *data; int ret = 0, i, j = AHASH_MAX_SIZE + 1; + bool flag_exist = flags & IPSET_FLAG_EXIST; u32 key; if (h->elements >= h->maxelem) @@ -800,7 +800,7 @@ type_pf_tadd(struct ip_set *set, void *value, u32 timeout) for (i = 0; i < n->pos; i++) { data = ahash_tdata(n, i); if (type_pf_data_equal(data, d)) { - if (type_pf_data_expired(data)) + if (type_pf_data_expired(data) || flag_exist) j = i; else { ret = -IPSET_ERR_EXIST; @@ -834,7 +834,7 @@ out: } static int -type_pf_tdel(struct ip_set *set, void *value, u32 timeout) +type_pf_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags) { struct ip_set_hash *h = set->data; struct htable *t = h->table; @@ -906,7 +906,7 @@ type_pf_ttest_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout) #endif static int -type_pf_ttest(struct ip_set *set, void *value, u32 timeout) +type_pf_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags) { struct ip_set_hash *h = set->data; struct htable *t = h->table; diff --git a/extensions/ipset-6/ip_set_bitmap_ip.c b/extensions/ipset-6/ip_set_bitmap_ip.c index 41cfded..cceac52 100644 --- a/extensions/ipset-6/ip_set_bitmap_ip.c +++ b/extensions/ipset-6/ip_set_bitmap_ip.c @@ -54,7 +54,7 @@ ip_to_id(const struct bitmap_ip *m, u32 ip) } static int -bitmap_ip_test(struct ip_set *set, void *value, u32 timeout) +bitmap_ip_test(struct ip_set *set, void *value, u32 timeout, u32 flags) { const struct bitmap_ip *map = set->data; u16 id = *(u16 *)value; @@ -63,7 +63,7 @@ bitmap_ip_test(struct ip_set *set, void *value, u32 timeout) } static int -bitmap_ip_add(struct ip_set *set, void *value, u32 timeout) +bitmap_ip_add(struct ip_set *set, void *value, u32 timeout, u32 flags) { struct bitmap_ip *map = set->data; u16 id = *(u16 *)value; @@ -75,7 +75,7 @@ bitmap_ip_add(struct ip_set *set, void *value, u32 timeout) } static int -bitmap_ip_del(struct ip_set *set, void *value, u32 timeout) +bitmap_ip_del(struct ip_set *set, void *value, u32 timeout, u32 flags) { struct bitmap_ip *map = set->data; u16 id = *(u16 *)value; @@ -131,7 +131,7 @@ nla_put_failure: /* Timeout variant */ static int -bitmap_ip_ttest(struct ip_set *set, void *value, u32 timeout) +bitmap_ip_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags) { const struct bitmap_ip *map = set->data; const unsigned long *members = map->members; @@ -141,13 +141,13 @@ bitmap_ip_ttest(struct ip_set *set, void *value, u32 timeout) } static int -bitmap_ip_tadd(struct ip_set *set, void *value, u32 timeout) +bitmap_ip_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags) { struct bitmap_ip *map = set->data; unsigned long *members = map->members; u16 id = *(u16 *)value; - if (ip_set_timeout_test(members[id])) + if (ip_set_timeout_test(members[id]) && !(flags & IPSET_FLAG_EXIST)) return -IPSET_ERR_EXIST; members[id] = ip_set_timeout_set(timeout); @@ -156,7 +156,7 @@ bitmap_ip_tadd(struct ip_set *set, void *value, u32 timeout) } static int -bitmap_ip_tdel(struct ip_set *set, void *value, u32 timeout) +bitmap_ip_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags) { struct bitmap_ip *map = set->data; unsigned long *members = map->members; @@ -231,7 +231,7 @@ bitmap_ip_kadt(struct ip_set *set, const struct sk_buff *skb, ip = ip_to_id(map, ip); - return adtfn(set, &ip, map->timeout); + return adtfn(set, &ip, map->timeout, flags); } static int @@ -266,7 +266,7 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[], if (adt == IPSET_TEST) { id = ip_to_id(map, ip); - return adtfn(set, &id, timeout); + return adtfn(set, &id, timeout, flags); } if (tb[IPSET_ATTR_IP_TO]) { @@ -293,7 +293,7 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[], for (; !before(ip_to, ip); ip += map->hosts) { id = ip_to_id(map, ip); - ret = adtfn(set, &id, timeout);; + ret = adtfn(set, &id, timeout, flags); if (ret && !ip_set_eexist(ret, flags)) return ret; @@ -338,8 +338,7 @@ bitmap_ip_head(struct ip_set *set, struct sk_buff *skb) NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip)); if (map->netmask != 32) NLA_PUT_U8(skb, IPSET_ATTR_NETMASK, map->netmask); - NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, - htonl(atomic_read(&set->ref) - 1)); + NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)); NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, htonl(sizeof(*map) + map->memsize)); if (with_timeout(map->timeout)) diff --git a/extensions/ipset-6/ip_set_bitmap_ipmac.c b/extensions/ipset-6/ip_set_bitmap_ipmac.c index 50fcb3f..74bca4c 100644 --- a/extensions/ipset-6/ip_set_bitmap_ipmac.c +++ b/extensions/ipset-6/ip_set_bitmap_ipmac.c @@ -99,7 +99,7 @@ bitmap_ipmac_exist(const struct ipmac_telem *elem) /* Base variant */ static int -bitmap_ipmac_test(struct ip_set *set, void *value, u32 timeout) +bitmap_ipmac_test(struct ip_set *set, void *value, u32 timeout, u32 flags) { const struct bitmap_ipmac *map = set->data; const struct ipmac *data = value; @@ -117,7 +117,7 @@ bitmap_ipmac_test(struct ip_set *set, void *value, u32 timeout) } static int -bitmap_ipmac_add(struct ip_set *set, void *value, u32 timeout) +bitmap_ipmac_add(struct ip_set *set, void *value, u32 timeout, u32 flags) { struct bitmap_ipmac *map = set->data; const struct ipmac *data = value; @@ -146,7 +146,7 @@ bitmap_ipmac_add(struct ip_set *set, void *value, u32 timeout) } static int -bitmap_ipmac_del(struct ip_set *set, void *value, u32 timeout) +bitmap_ipmac_del(struct ip_set *set, void *value, u32 timeout, u32 flags) { struct bitmap_ipmac *map = set->data; const struct ipmac *data = value; @@ -212,7 +212,7 @@ nla_put_failure: /* Timeout variant */ static int -bitmap_ipmac_ttest(struct ip_set *set, void *value, u32 timeout) +bitmap_ipmac_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags) { const struct bitmap_ipmac *map = set->data; const struct ipmac *data = value; @@ -231,15 +231,16 @@ bitmap_ipmac_ttest(struct ip_set *set, void *value, u32 timeout) } static int -bitmap_ipmac_tadd(struct ip_set *set, void *value, u32 timeout) +bitmap_ipmac_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags) { struct bitmap_ipmac *map = set->data; const struct ipmac *data = value; struct ipmac_telem *elem = bitmap_ipmac_elem(map, data->id); + bool flag_exist = flags & IPSET_FLAG_EXIST; switch (elem->match) { case MAC_UNSET: - if (!data->ether) + if (!(data->ether || flag_exist)) /* Already added without ethernet address */ return -IPSET_ERR_EXIST; /* Fill the MAC address and activate the timer */ @@ -251,7 +252,7 @@ bitmap_ipmac_tadd(struct ip_set *set, void *value, u32 timeout) elem->timeout = ip_set_timeout_set(timeout); break; case MAC_FILLED: - if (!bitmap_expired(map, data->id)) + if (!(bitmap_expired(map, data->id) || flag_exist)) return -IPSET_ERR_EXIST; /* Fall through */ case MAC_EMPTY: @@ -273,7 +274,7 @@ bitmap_ipmac_tadd(struct ip_set *set, void *value, u32 timeout) } static int -bitmap_ipmac_tdel(struct ip_set *set, void *value, u32 timeout) +bitmap_ipmac_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags) { struct bitmap_ipmac *map = set->data; const struct ipmac *data = value; @@ -355,7 +356,7 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb, data.id -= map->first_ip; data.ether = eth_hdr(skb)->h_source; - return adtfn(set, &data, map->timeout); + return adtfn(set, &data, map->timeout, flags); } static int @@ -395,7 +396,7 @@ bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *tb[], data.id -= map->first_ip; - ret = adtfn(set, &data, timeout); + ret = adtfn(set, &data, timeout, flags); return ip_set_eexist(ret, flags) ? 0 : ret; } @@ -434,8 +435,7 @@ bitmap_ipmac_head(struct ip_set *set, struct sk_buff *skb) goto nla_put_failure; NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, htonl(map->first_ip)); NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip)); - NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, - htonl(atomic_read(&set->ref) - 1)); + NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)); NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, htonl(sizeof(*map) + (map->last_ip - map->first_ip + 1) * map->dsize)); diff --git a/extensions/ipset-6/ip_set_bitmap_port.c b/extensions/ipset-6/ip_set_bitmap_port.c index 01dc2ff..6512542 100644 --- a/extensions/ipset-6/ip_set_bitmap_port.c +++ b/extensions/ipset-6/ip_set_bitmap_port.c @@ -40,7 +40,7 @@ struct bitmap_port { /* Base variant */ static int -bitmap_port_test(struct ip_set *set, void *value, u32 timeout) +bitmap_port_test(struct ip_set *set, void *value, u32 timeout, u32 flags) { const struct bitmap_port *map = set->data; u16 id = *(u16 *)value; @@ -49,7 +49,7 @@ bitmap_port_test(struct ip_set *set, void *value, u32 timeout) } static int -bitmap_port_add(struct ip_set *set, void *value, u32 timeout) +bitmap_port_add(struct ip_set *set, void *value, u32 timeout, u32 flags) { struct bitmap_port *map = set->data; u16 id = *(u16 *)value; @@ -61,7 +61,7 @@ bitmap_port_add(struct ip_set *set, void *value, u32 timeout) } static int -bitmap_port_del(struct ip_set *set, void *value, u32 timeout) +bitmap_port_del(struct ip_set *set, void *value, u32 timeout, u32 flags) { struct bitmap_port *map = set->data; u16 id = *(u16 *)value; @@ -119,7 +119,7 @@ nla_put_failure: /* Timeout variant */ static int -bitmap_port_ttest(struct ip_set *set, void *value, u32 timeout) +bitmap_port_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags) { const struct bitmap_port *map = set->data; const unsigned long *members = map->members; @@ -129,13 +129,13 @@ bitmap_port_ttest(struct ip_set *set, void *value, u32 timeout) } static int -bitmap_port_tadd(struct ip_set *set, void *value, u32 timeout) +bitmap_port_tadd(struct ip_set *set, void *value, u32 timeout, u32 flags) { struct bitmap_port *map = set->data; unsigned long *members = map->members; u16 id = *(u16 *)value; - if (ip_set_timeout_test(members[id])) + if (ip_set_timeout_test(members[id]) && !(flags & IPSET_FLAG_EXIST)) return -IPSET_ERR_EXIST; members[id] = ip_set_timeout_set(timeout); @@ -144,7 +144,7 @@ bitmap_port_tadd(struct ip_set *set, void *value, u32 timeout) } static int -bitmap_port_tdel(struct ip_set *set, void *value, u32 timeout) +bitmap_port_tdel(struct ip_set *set, void *value, u32 timeout, u32 flags) { struct bitmap_port *map = set->data; unsigned long *members = map->members; @@ -225,7 +225,7 @@ bitmap_port_kadt(struct ip_set *set, const struct sk_buff *skb, port -= map->first_port; - return adtfn(set, &port, map->timeout); + return adtfn(set, &port, map->timeout, flags); } static int @@ -259,7 +259,7 @@ bitmap_port_uadt(struct ip_set *set, struct nlattr *tb[], if (adt == IPSET_TEST) { id = port - map->first_port; - return adtfn(set, &id, timeout); + return adtfn(set, &id, timeout, flags); } if (tb[IPSET_ATTR_PORT_TO]) { @@ -277,7 +277,7 @@ bitmap_port_uadt(struct ip_set *set, struct nlattr *tb[], for (; port <= port_to; port++) { id = port - map->first_port; - ret = adtfn(set, &id, timeout); + ret = adtfn(set, &id, timeout, flags); if (ret && !ip_set_eexist(ret, flags)) return ret; @@ -320,8 +320,7 @@ bitmap_port_head(struct ip_set *set, struct sk_buff *skb) goto nla_put_failure; NLA_PUT_NET16(skb, IPSET_ATTR_PORT, htons(map->first_port)); NLA_PUT_NET16(skb, IPSET_ATTR_PORT_TO, htons(map->last_port)); - NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, - htonl(atomic_read(&set->ref) - 1)); + NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)); NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, htonl(sizeof(*map) + map->memsize)); if (with_timeout(map->timeout)) diff --git a/extensions/ipset-6/ip_set_core.c b/extensions/ipset-6/ip_set_core.c index 83da444..abf1c90 100644 --- a/extensions/ipset-6/ip_set_core.c +++ b/extensions/ipset-6/ip_set_core.c @@ -28,6 +28,7 @@ static LIST_HEAD(ip_set_type_list); /* all registered set types */ static DEFINE_MUTEX(ip_set_type_mutex); /* protects ip_set_type_list */ +static DEFINE_RWLOCK(ip_set_ref_lock); /* protects the set refs */ static struct ip_set **ip_set_list; /* all individual sets */ static ip_set_id_t ip_set_max = LCONFIG_IP_SET_MAX; /* max number of sets */ @@ -97,16 +98,28 @@ static int find_set_type_get(const char *name, u8 family, u8 revision, struct ip_set_type **found) { + struct ip_set_type *type; + int err; + rcu_read_lock(); *found = find_set_type(name, family, revision); if (*found) { - int err = !try_module_get((*found)->me); - rcu_read_unlock(); - return err ? -EFAULT : 0; + err = !try_module_get((*found)->me) ? -EFAULT : 0; + goto unlock; } + /* Make sure the type is loaded but we don't support the revision */ + list_for_each_entry_rcu(type, &ip_set_type_list, list) + if (STREQ(type->name, name)) { + err = -IPSET_ERR_FIND_TYPE; + goto unlock; + } rcu_read_unlock(); return try_to_load_type(name); + +unlock: + rcu_read_unlock(); + return err; } /* Find a given set type by name and family. @@ -119,7 +132,7 @@ find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max) struct ip_set_type *type; bool found = false; - *min = *max = 0; + *min = 255; *max = 0; rcu_read_lock(); list_for_each_entry_rcu(type, &ip_set_type_list, list) if (STREQ(type->name, name) && @@ -127,7 +140,7 @@ find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max) found = true; if (type->revision < *min) *min = type->revision; - else if (type->revision > *max) + if (type->revision > *max) *max = type->revision; } rcu_read_unlock(); @@ -297,13 +310,18 @@ EXPORT_SYMBOL_GPL(ip_set_get_ipaddr6); static inline void __ip_set_get(ip_set_id_t index) { - atomic_inc(&ip_set_list[index]->ref); + write_lock_bh(&ip_set_ref_lock); + ip_set_list[index]->ref++; + write_unlock_bh(&ip_set_ref_lock); } static inline void __ip_set_put(ip_set_id_t index) { - atomic_dec(&ip_set_list[index]->ref); + write_lock_bh(&ip_set_ref_lock); + BUG_ON(ip_set_list[index]->ref == 0); + ip_set_list[index]->ref--; + write_unlock_bh(&ip_set_ref_lock); } /* @@ -320,7 +338,7 @@ ip_set_test(ip_set_id_t index, const struct sk_buff *skb, struct ip_set *set = ip_set_list[index]; int ret = 0; - BUG_ON(set == NULL || atomic_read(&set->ref) == 0); + BUG_ON(set == NULL); pr_debug("set %s, index %u\n", set->name, index); if (dim < set->type->dimension || @@ -352,7 +370,7 @@ ip_set_add(ip_set_id_t index, const struct sk_buff *skb, struct ip_set *set = ip_set_list[index]; int ret; - BUG_ON(set == NULL || atomic_read(&set->ref) == 0); + BUG_ON(set == NULL); pr_debug("set %s, index %u\n", set->name, index); if (dim < set->type->dimension || @@ -374,7 +392,7 @@ ip_set_del(ip_set_id_t index, const struct sk_buff *skb, struct ip_set *set = ip_set_list[index]; int ret = 0; - BUG_ON(set == NULL || atomic_read(&set->ref) == 0); + BUG_ON(set == NULL); pr_debug("set %s, index %u\n", set->name, index); if (dim < set->type->dimension || @@ -393,7 +411,6 @@ EXPORT_SYMBOL_GPL(ip_set_del); * Find set by name, reference it once. The reference makes sure the * thing pointed to, does not go away under our feet. * - * The nfnl mutex must already be activated. */ ip_set_id_t ip_set_get_byname(const char *name, struct ip_set **set) @@ -419,15 +436,12 @@ EXPORT_SYMBOL_GPL(ip_set_get_byname); * reference count by 1. The caller shall not assume the index * to be valid, after calling this function. * - * The nfnl mutex must already be activated. */ void ip_set_put_byindex(ip_set_id_t index) { - if (ip_set_list[index] != NULL) { - BUG_ON(atomic_read(&ip_set_list[index]->ref) == 0); + if (ip_set_list[index] != NULL) __ip_set_put(index); - } } EXPORT_SYMBOL_GPL(ip_set_put_byindex); @@ -437,7 +451,6 @@ EXPORT_SYMBOL_GPL(ip_set_put_byindex); * can't be destroyed. The set cannot be renamed due to * the referencing either. * - * The nfnl mutex must already be activated. */ const char * ip_set_name_byindex(ip_set_id_t index) @@ -445,7 +458,7 @@ ip_set_name_byindex(ip_set_id_t index) const struct ip_set *set = ip_set_list[index]; BUG_ON(set == NULL); - BUG_ON(atomic_read(&set->ref) == 0); + BUG_ON(set->ref == 0); /* Referenced, so it's safe */ return set->name; @@ -511,10 +524,7 @@ void ip_set_nfnl_put(ip_set_id_t index) { nfnl_lock(); - if (ip_set_list[index] != NULL) { - BUG_ON(atomic_read(&ip_set_list[index]->ref) == 0); - __ip_set_put(index); - } + ip_set_put_byindex(index); nfnl_unlock(); } EXPORT_SYMBOL_GPL(ip_set_nfnl_put); @@ -522,7 +532,7 @@ EXPORT_SYMBOL_GPL(ip_set_nfnl_put); /* * Communication protocol with userspace over netlink. * - * We already locked by nfnl_lock. + * The commands are serialized by the nfnl mutex. */ static inline bool @@ -611,8 +621,7 @@ static int ip_set_create(struct sk_buff *skb, struct genl_info *info) { struct nlattr *const *attr = info->attrs; - - struct ip_set *set, *clash; + struct ip_set *set, *clash = NULL; ip_set_id_t index = IPSET_INVALID_ID; struct nlattr *tb[IPSET_ATTR_CREATE_MAX+1] = {}; const char *name, *typename; @@ -645,7 +654,6 @@ ip_set_create(struct sk_buff *skb, struct genl_info *info) return -ENOMEM; rwlock_init(&set->lock); strlcpy(set->name, name, IPSET_MAXNAMELEN); - atomic_set(&set->ref, 0); set->family = family; /* @@ -678,8 +686,8 @@ ip_set_create(struct sk_buff *skb, struct genl_info *info) /* * Here, we have a valid, constructed set and we are protected - * by nfnl_lock. Find the first free index in ip_set_list and - * check clashing. + * by the nfnl mutex. Find the first free index in ip_set_list + * and check clashing. */ if ((ret = find_free_id(set->name, &index, &clash)) != 0) { /* If this is the same set and requested, ignore error */ @@ -738,31 +746,51 @@ ip_set_destroy(struct sk_buff *skb, struct genl_info *info) { struct nlattr *const *attr = info->attrs; ip_set_id_t i; + int ret = 0; if (unlikely(protocol_failed(attr))) return -IPSET_ERR_PROTOCOL; - /* References are protected by the nfnl mutex */ + /* Commands are serialized and references are + * protected by the ip_set_ref_lock. + * External systems (i.e. xt_set) must call + * ip_set_put|get_nfnl_* functions, that way we + * can safely check references here. + * + * list:set timer can only decrement the reference + * counter, so if it's already zero, we can proceed + * without holding the lock. + */ + read_lock_bh(&ip_set_ref_lock); if (!attr[IPSET_ATTR_SETNAME]) { for (i = 0; i < ip_set_max; i++) { - if (ip_set_list[i] != NULL && - (atomic_read(&ip_set_list[i]->ref))) - return -IPSET_ERR_BUSY; + if (ip_set_list[i] != NULL && ip_set_list[i]->ref) { + ret = IPSET_ERR_BUSY; + goto out; + } } + read_unlock_bh(&ip_set_ref_lock); for (i = 0; i < ip_set_max; i++) { if (ip_set_list[i] != NULL) ip_set_destroy_set(i); } } else { i = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME])); - if (i == IPSET_INVALID_ID) - return -ENOENT; - else if (atomic_read(&ip_set_list[i]->ref)) - return -IPSET_ERR_BUSY; + if (i == IPSET_INVALID_ID) { + ret = -ENOENT; + goto out; + } else if (ip_set_list[i]->ref) { + ret = -IPSET_ERR_BUSY; + goto out; + } + read_unlock_bh(&ip_set_ref_lock); ip_set_destroy_set(i); } return 0; +out: + read_unlock_bh(&ip_set_ref_lock); + return ret; } /* Flush sets */ @@ -819,6 +847,7 @@ ip_set_rename(struct sk_buff *skb, struct genl_info *info) struct ip_set *set; const char *name2; ip_set_id_t i; + int ret = 0; if (unlikely(protocol_failed(attr) || attr[IPSET_ATTR_SETNAME] == NULL || @@ -828,25 +857,33 @@ ip_set_rename(struct sk_buff *skb, struct genl_info *info) set = find_set(nla_data(attr[IPSET_ATTR_SETNAME])); if (set == NULL) return -ENOENT; - if (atomic_read(&set->ref) != 0) - return -IPSET_ERR_REFERENCED; + + read_lock_bh(&ip_set_ref_lock); + if (set->ref != 0) { + ret = -IPSET_ERR_REFERENCED; + goto out; + } name2 = nla_data(attr[IPSET_ATTR_SETNAME2]); for (i = 0; i < ip_set_max; i++) { if (ip_set_list[i] != NULL && - STREQ(ip_set_list[i]->name, name2)) - return -IPSET_ERR_EXIST_SETNAME2; + STREQ(ip_set_list[i]->name, name2)) { + ret = -IPSET_ERR_EXIST_SETNAME2; + goto out; + } } strncpy(set->name, name2, IPSET_MAXNAMELEN); - return 0; +out: + read_unlock_bh(&ip_set_ref_lock); + return ret; } /* Swap two sets so that name/index points to the other. * References and set names are also swapped. * - * We are protected by the nfnl mutex and references are - * manipulated only by holding the mutex. The kernel interfaces + * The commands are serialized by the nfnl mutex and references are + * protected by the ip_set_ref_lock. The kernel interfaces * do not hold the mutex but the pointer settings are atomic * so the ip_set_list always contains valid pointers to the sets. */ @@ -858,7 +895,6 @@ ip_set_swap(struct sk_buff *skb, struct genl_info *info) struct ip_set *from, *to; ip_set_id_t from_id, to_id; char from_name[IPSET_MAXNAMELEN]; - u32 from_ref; if (unlikely(protocol_failed(attr) || attr[IPSET_ATTR_SETNAME] == NULL || @@ -883,17 +919,15 @@ ip_set_swap(struct sk_buff *skb, struct genl_info *info) from->type->family == to->type->family)) return -IPSET_ERR_TYPE_MISMATCH; - /* No magic here: ref munging protected by the nfnl_lock */ strncpy(from_name, from->name, IPSET_MAXNAMELEN); - from_ref = atomic_read(&from->ref); - strncpy(from->name, to->name, IPSET_MAXNAMELEN); - atomic_set(&from->ref, atomic_read(&to->ref)); strncpy(to->name, from_name, IPSET_MAXNAMELEN); - atomic_set(&to->ref, from_ref); + write_lock_bh(&ip_set_ref_lock); + swap(from->ref, to->ref); ip_set_list[from_id] = to; ip_set_list[to_id] = from; + write_unlock_bh(&ip_set_ref_lock); return 0; } @@ -910,7 +944,7 @@ ip_set_dump_done(struct netlink_callback *cb) { if (cb->args[2]) { pr_debug("release set %s\n", ip_set_list[cb->args[1]]->name); - __ip_set_put((ip_set_id_t) cb->args[1]); + ip_set_put_byindex((ip_set_id_t) cb->args[1]); } return 0; } @@ -1053,7 +1087,7 @@ release_refcount: /* If there was an error or set is done, release set */ if (ret || !cb->args[2]) { pr_debug("release set %s\n", ip_set_list[index]->name); - __ip_set_put(index); + ip_set_put_byindex(index); } /* If we dump all sets, continue with dumping last ones */ diff --git a/extensions/ipset-6/ip_set_getport.c b/extensions/ipset-6/ip_set_getport.c index 0daf5e5..8600041 100644 --- a/extensions/ipset-6/ip_set_getport.c +++ b/extensions/ipset-6/ip_set_getport.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -35,7 +36,20 @@ get_port(const struct sk_buff *skb, int protocol, unsigned int protooff, *port = src ? th->source : th->dest; break; } - case IPPROTO_UDP: { + case IPPROTO_SCTP: { + sctp_sctphdr_t _sh; + const sctp_sctphdr_t *sh; + + sh = skb_header_pointer(skb, protooff, sizeof(_sh), &_sh); + if (sh == NULL) + /* No choice either */ + return false; + + *port = src ? sh->source : sh->dest; + break; + } + case IPPROTO_UDP: + case IPPROTO_UDPLITE: { struct udphdr _udph; const struct udphdr *uh; diff --git a/extensions/ipset-6/ip_set_getport.h b/extensions/ipset-6/ip_set_getport.h index 3882a81..90d0930 100644 --- a/extensions/ipset-6/ip_set_getport.h +++ b/extensions/ipset-6/ip_set_getport.h @@ -18,4 +18,16 @@ static inline bool ip_set_get_ip6_port(const struct sk_buff *skb, bool src, extern bool ip_set_get_ip_port(const struct sk_buff *skb, u8 pf, bool src, __be16 *port); +static inline bool ip_set_proto_with_ports(u8 proto) +{ + switch (proto) { + case IPPROTO_TCP: + case IPPROTO_SCTP: + case IPPROTO_UDP: + case IPPROTO_UDPLITE: + return true; + } + return false; +} + #endif /*_IP_SET_GETPORT_H*/ diff --git a/extensions/ipset-6/ip_set_hash_ip.c b/extensions/ipset-6/ip_set_hash_ip.c index 5bc3a9a..94092f3 100644 --- a/extensions/ipset-6/ip_set_hash_ip.c +++ b/extensions/ipset-6/ip_set_hash_ip.c @@ -121,7 +121,7 @@ hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb, if (ip == 0) return -EINVAL; - return adtfn(set, &ip, h->timeout); + return adtfn(set, &ip, h->timeout, flags); } static int @@ -157,7 +157,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[], nip = htonl(ip); if (nip == 0) return -IPSET_ERR_HASH_ELEM; - return adtfn(set, &nip, timeout); + return adtfn(set, &nip, timeout, flags); } if (tb[IPSET_ATTR_IP_TO]) { @@ -182,7 +182,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[], nip = htonl(ip); if (nip == 0) return -IPSET_ERR_HASH_ELEM; - ret = adtfn(set, &nip, timeout); + ret = adtfn(set, &nip, timeout, flags); if (ret && !ip_set_eexist(ret, flags)) return ret; @@ -294,7 +294,7 @@ hash_ip6_kadt(struct ip_set *set, const struct sk_buff *skb, if (ipv6_addr_any(&ip.in6)) return -EINVAL; - return adtfn(set, &ip, h->timeout); + return adtfn(set, &ip, h->timeout, flags); } static const struct nla_policy hash_ip6_adt_policy[IPSET_ATTR_ADT_MAX + 1] = { @@ -336,7 +336,7 @@ hash_ip6_uadt(struct ip_set *set, struct nlattr *tb[], timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); } - ret = adtfn(set, &ip, timeout); + ret = adtfn(set, &ip, timeout, flags); return ip_set_eexist(ret, flags) ? 0 : ret; } diff --git a/extensions/ipset-6/ip_set_hash_ipport.c b/extensions/ipset-6/ip_set_hash_ipport.c index a2530e6..e8b506a 100644 --- a/extensions/ipset-6/ip_set_hash_ipport.c +++ b/extensions/ipset-6/ip_set_hash_ipport.c @@ -138,7 +138,7 @@ hash_ipport4_kadt(struct ip_set *set, const struct sk_buff *skb, ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip); - return adtfn(set, &data, h->timeout); + return adtfn(set, &data, h->timeout, flags); } static int @@ -150,6 +150,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], struct hash_ipport4_elem data = { }; u32 ip, ip_to, p, port, port_to; u32 timeout = h->timeout; + bool with_ports = false; int ret; if (unlikely(!tb[IPSET_ATTR_IP] || @@ -172,21 +173,15 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], if (tb[IPSET_ATTR_PROTO]) { data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); + with_ports = ip_set_proto_with_ports(data.proto); if (data.proto == 0) return -IPSET_ERR_INVALID_PROTO; } else return -IPSET_ERR_MISSING_PROTO; - switch (data.proto) { - case IPPROTO_UDP: - case IPPROTO_TCP: - case IPPROTO_ICMP: - break; - default: + if (!(with_ports || data.proto == IPPROTO_ICMP)) data.port = 0; - break; - } if (tb[IPSET_ATTR_TIMEOUT]) { if (!with_timeout(h->timeout)) @@ -195,10 +190,9 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], } if (adt == IPSET_TEST || - !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || tb[IPSET_ATTR_PORT_TO])) { - ret = adtfn(set, &data, timeout); + ret = adtfn(set, &data, timeout, flags); return ip_set_eexist(ret, flags) ? 0 : ret; } @@ -219,19 +213,18 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], } else ip_to = ip; - port = ntohs(data.port); - if (tb[IPSET_ATTR_PORT_TO]) { + port_to = port = ntohs(data.port); + if (with_ports && tb[IPSET_ATTR_PORT_TO]) { port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); if (port > port_to) swap(port, port_to); - } else - port_to = port; + } for (; !before(ip_to, ip); ip++) for (p = port; p <= port_to; p++) { data.ip = htonl(ip); data.port = htons(p); - ret = adtfn(set, &data, timeout); + ret = adtfn(set, &data, timeout, flags); if (ret && !ip_set_eexist(ret, flags)) return ret; @@ -349,7 +342,7 @@ hash_ipport6_kadt(struct ip_set *set, const struct sk_buff *skb, ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6); - return adtfn(set, &data, h->timeout); + return adtfn(set, &data, h->timeout, flags); } static int @@ -361,6 +354,7 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[], struct hash_ipport6_elem data = { }; u32 port, port_to; u32 timeout = h->timeout; + bool with_ports = false; int ret; if (unlikely(!tb[IPSET_ATTR_IP] || @@ -385,21 +379,15 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[], if (tb[IPSET_ATTR_PROTO]) { data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); + with_ports = ip_set_proto_with_ports(data.proto); if (data.proto == 0) return -IPSET_ERR_INVALID_PROTO; } else return -IPSET_ERR_MISSING_PROTO; - switch (data.proto) { - case IPPROTO_UDP: - case IPPROTO_TCP: - case IPPROTO_ICMPV6: - break; - default: + if (!(with_ports || data.proto == IPPROTO_ICMPV6)) data.port = 0; - break; - } if (tb[IPSET_ATTR_TIMEOUT]) { if (!with_timeout(h->timeout)) @@ -407,10 +395,8 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[], timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); } - if (adt == IPSET_TEST || - !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || - !tb[IPSET_ATTR_PORT_TO]) { - ret = adtfn(set, &data, timeout); + if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { + ret = adtfn(set, &data, timeout, flags); return ip_set_eexist(ret, flags) ? 0 : ret; } @@ -421,7 +407,7 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[], for (; port <= port_to; port++) { data.port = htons(port); - ret = adtfn(set, &data, timeout); + ret = adtfn(set, &data, timeout, flags); if (ret && !ip_set_eexist(ret, flags)) return ret; @@ -505,7 +491,7 @@ static struct ip_set_type hash_ipport_type __read_mostly = { .features = IPSET_TYPE_IP | IPSET_TYPE_PORT, .dimension = IPSET_DIM_TWO, .family = AF_UNSPEC, - .revision = 0, + .revision = 1, .create = hash_ipport_create, .create_policy = { [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, diff --git a/extensions/ipset-6/ip_set_hash_ipportip.c b/extensions/ipset-6/ip_set_hash_ipportip.c index a6d1797..f7726b3 100644 --- a/extensions/ipset-6/ip_set_hash_ipportip.c +++ b/extensions/ipset-6/ip_set_hash_ipportip.c @@ -142,7 +142,7 @@ hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb, ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip); ip4addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2); - return adtfn(set, &data, h->timeout); + return adtfn(set, &data, h->timeout, flags); } static int @@ -154,6 +154,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], struct hash_ipportip4_elem data = { }; u32 ip, ip_to, p, port, port_to; u32 timeout = h->timeout; + bool with_ports = false; int ret; if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || @@ -180,21 +181,15 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], if (tb[IPSET_ATTR_PROTO]) { data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); + with_ports = ip_set_proto_with_ports(data.proto); if (data.proto == 0) return -IPSET_ERR_INVALID_PROTO; } else return -IPSET_ERR_MISSING_PROTO; - switch (data.proto) { - case IPPROTO_UDP: - case IPPROTO_TCP: - case IPPROTO_ICMP: - break; - default: + if (!(with_ports || data.proto == IPPROTO_ICMP)) data.port = 0; - break; - } if (tb[IPSET_ATTR_TIMEOUT]) { if (!with_timeout(h->timeout)) @@ -203,10 +198,9 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], } if (adt == IPSET_TEST || - !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || tb[IPSET_ATTR_PORT_TO])) { - ret = adtfn(set, &data, timeout); + ret = adtfn(set, &data, timeout, flags); return ip_set_eexist(ret, flags) ? 0 : ret; } @@ -227,19 +221,18 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], } else ip_to = ip; - port = ntohs(data.port); - if (tb[IPSET_ATTR_PORT_TO]) { + port_to = port = ntohs(data.port); + if (with_ports && tb[IPSET_ATTR_PORT_TO]) { port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); if (port > port_to) swap(port, port_to); - } else - port_to = port; + } for (; !before(ip_to, ip); ip++) for (p = port; p <= port_to; p++) { data.ip = htonl(ip); data.port = htons(p); - ret = adtfn(set, &data, timeout); + ret = adtfn(set, &data, timeout, flags); if (ret && !ip_set_eexist(ret, flags)) return ret; @@ -363,7 +356,7 @@ hash_ipportip6_kadt(struct ip_set *set, const struct sk_buff *skb, ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6); ip6addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2.in6); - return adtfn(set, &data, h->timeout); + return adtfn(set, &data, h->timeout, flags); } static int @@ -375,6 +368,7 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[], struct hash_ipportip6_elem data = { }; u32 port, port_to; u32 timeout = h->timeout; + bool with_ports = false; int ret; if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || @@ -403,21 +397,15 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[], if (tb[IPSET_ATTR_PROTO]) { data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); + with_ports = ip_set_proto_with_ports(data.proto); if (data.proto == 0) return -IPSET_ERR_INVALID_PROTO; } else return -IPSET_ERR_MISSING_PROTO; - switch (data.proto) { - case IPPROTO_UDP: - case IPPROTO_TCP: - case IPPROTO_ICMPV6: - break; - default: + if (!(with_ports || data.proto == IPPROTO_ICMPV6)) data.port = 0; - break; - } if (tb[IPSET_ATTR_TIMEOUT]) { if (!with_timeout(h->timeout)) @@ -425,10 +413,8 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[], timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); } - if (adt == IPSET_TEST || - !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || - !tb[IPSET_ATTR_PORT_TO]) { - ret = adtfn(set, &data, timeout); + if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { + ret = adtfn(set, &data, timeout, flags); return ip_set_eexist(ret, flags) ? 0 : ret; } @@ -439,7 +425,7 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[], for (; port <= port_to; port++) { data.port = htons(port); - ret = adtfn(set, &data, timeout); + ret = adtfn(set, &data, timeout, flags); if (ret && !ip_set_eexist(ret, flags)) return ret; @@ -523,7 +509,7 @@ static struct ip_set_type hash_ipportip_type __read_mostly = { .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2, .dimension = IPSET_DIM_THREE, .family = AF_UNSPEC, - .revision = 0, + .revision = 1, .create = hash_ipportip_create, .create_policy = { [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, diff --git a/extensions/ipset-6/ip_set_hash_ipportnet.c b/extensions/ipset-6/ip_set_hash_ipportnet.c index 258eeb9..52d5353 100644 --- a/extensions/ipset-6/ip_set_hash_ipportnet.c +++ b/extensions/ipset-6/ip_set_hash_ipportnet.c @@ -162,7 +162,7 @@ hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb, ip4addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2); data.ip2 &= ip_set_netmask(data.cidr); - return adtfn(set, &data, h->timeout); + return adtfn(set, &data, h->timeout, flags); } static int @@ -174,6 +174,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], struct hash_ipportnet4_elem data = { .cidr = HOST_MASK }; u32 ip, ip_to, p, port, port_to; u32 timeout = h->timeout; + bool with_ports = false; int ret; if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || @@ -208,21 +209,15 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], if (tb[IPSET_ATTR_PROTO]) { data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); + with_ports = ip_set_proto_with_ports(data.proto); if (data.proto == 0) return -IPSET_ERR_INVALID_PROTO; } else return -IPSET_ERR_MISSING_PROTO; - switch (data.proto) { - case IPPROTO_UDP: - case IPPROTO_TCP: - case IPPROTO_ICMP: - break; - default: + if (!(with_ports || data.proto == IPPROTO_ICMP)) data.port = 0; - break; - } if (tb[IPSET_ATTR_TIMEOUT]) { if (!with_timeout(h->timeout)) @@ -231,10 +226,9 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], } if (adt == IPSET_TEST || - !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] || tb[IPSET_ATTR_PORT_TO])) { - ret = adtfn(set, &data, timeout); + ret = adtfn(set, &data, timeout, flags); return ip_set_eexist(ret, flags) ? 0 : ret; } @@ -255,19 +249,18 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], } else ip_to = ip; - port = ntohs(data.port); - if (tb[IPSET_ATTR_PORT_TO]) { + port_to = port = ntohs(data.port); + if (with_ports && tb[IPSET_ATTR_PORT_TO]) { port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]); if (port > port_to) swap(port, port_to); - } else - port_to = port; + } for (; !before(ip_to, ip); ip++) for (p = port; p <= port_to; p++) { data.ip = htonl(ip); data.port = htons(p); - ret = adtfn(set, &data, timeout); + ret = adtfn(set, &data, timeout, flags); if (ret && !ip_set_eexist(ret, flags)) return ret; @@ -417,7 +410,7 @@ hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb, ip6addrptr(skb, flags & IPSET_DIM_THREE_SRC, &data.ip2.in6); ip6_netmask(&data.ip2, data.cidr); - return adtfn(set, &data, h->timeout); + return adtfn(set, &data, h->timeout, flags); } static int @@ -429,6 +422,7 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[], struct hash_ipportnet6_elem data = { .cidr = HOST_MASK }; u32 port, port_to; u32 timeout = h->timeout; + bool with_ports = false; int ret; if (unlikely(!tb[IPSET_ATTR_IP] || !tb[IPSET_ATTR_IP2] || @@ -465,21 +459,15 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[], if (tb[IPSET_ATTR_PROTO]) { data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); + with_ports = ip_set_proto_with_ports(data.proto); if (data.proto == 0) return -IPSET_ERR_INVALID_PROTO; } else return -IPSET_ERR_MISSING_PROTO; - switch (data.proto) { - case IPPROTO_UDP: - case IPPROTO_TCP: - case IPPROTO_ICMPV6: - break; - default: + if (!(with_ports || data.proto == IPPROTO_ICMPV6)) data.port = 0; - break; - } if (tb[IPSET_ATTR_TIMEOUT]) { if (!with_timeout(h->timeout)) @@ -487,10 +475,8 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[], timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); } - if (adt == IPSET_TEST || - !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || - !tb[IPSET_ATTR_PORT_TO]) { - ret = adtfn(set, &data, timeout); + if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { + ret = adtfn(set, &data, timeout, flags); return ip_set_eexist(ret, flags) ? 0 : ret; } @@ -501,7 +487,7 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[], for (; port <= port_to; port++) { data.port = htons(port); - ret = adtfn(set, &data, timeout); + ret = adtfn(set, &data, timeout, flags); if (ret && !ip_set_eexist(ret, flags)) return ret; @@ -588,7 +574,7 @@ static struct ip_set_type hash_ipportnet_type __read_mostly = { .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2, .dimension = IPSET_DIM_THREE, .family = AF_UNSPEC, - .revision = 0, + .revision = 1, .create = hash_ipportnet_create, .create_policy = { [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, diff --git a/extensions/ipset-6/ip_set_hash_net.c b/extensions/ipset-6/ip_set_hash_net.c index c5d0722..9f1b14e 100644 --- a/extensions/ipset-6/ip_set_hash_net.c +++ b/extensions/ipset-6/ip_set_hash_net.c @@ -141,7 +141,7 @@ hash_net4_kadt(struct ip_set *set, const struct sk_buff *skb, ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip); data.ip &= ip_set_netmask(data.cidr); - return adtfn(set, &data, h->timeout); + return adtfn(set, &data, h->timeout, flags); } static int @@ -179,7 +179,7 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[], timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); } - ret = adtfn(set, &data, timeout); + ret = adtfn(set, &data, timeout, flags); return ip_set_eexist(ret, flags) ? 0 : ret; } @@ -306,7 +306,7 @@ hash_net6_kadt(struct ip_set *set, const struct sk_buff *skb, ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6); ip6_netmask(&data.ip, data.cidr); - return adtfn(set, &data, h->timeout); + return adtfn(set, &data, h->timeout, flags); } static int @@ -344,7 +344,7 @@ hash_net6_uadt(struct ip_set *set, struct nlattr *tb[], timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); } - ret = adtfn(set, &data, timeout); + ret = adtfn(set, &data, timeout, flags); return ip_set_eexist(ret, flags) ? 0 : ret; } diff --git a/extensions/ipset-6/ip_set_hash_netport.c b/extensions/ipset-6/ip_set_hash_netport.c index 249c5b3..989d266 100644 --- a/extensions/ipset-6/ip_set_hash_netport.c +++ b/extensions/ipset-6/ip_set_hash_netport.c @@ -158,7 +158,7 @@ hash_netport4_kadt(struct ip_set *set, const struct sk_buff *skb, ip4addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip); data.ip &= ip_set_netmask(data.cidr); - return adtfn(set, &data, h->timeout); + return adtfn(set, &data, h->timeout, flags); } static int @@ -170,6 +170,7 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[], struct hash_netport4_elem data = { .cidr = HOST_MASK }; u32 port, port_to; u32 timeout = h->timeout; + bool with_ports = false; int ret; if (unlikely(!tb[IPSET_ATTR_IP] || @@ -198,21 +199,15 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[], if (tb[IPSET_ATTR_PROTO]) { data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); + with_ports = ip_set_proto_with_ports(data.proto); if (data.proto == 0) return -IPSET_ERR_INVALID_PROTO; } else return -IPSET_ERR_MISSING_PROTO; - switch (data.proto) { - case IPPROTO_UDP: - case IPPROTO_TCP: - case IPPROTO_ICMP: - break; - default: + if (!(with_ports || data.proto == IPPROTO_ICMP)) data.port = 0; - break; - } if (tb[IPSET_ATTR_TIMEOUT]) { if (!with_timeout(h->timeout)) @@ -220,10 +215,8 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[], timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); } - if (adt == IPSET_TEST || - !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || - !tb[IPSET_ATTR_PORT_TO]) { - ret = adtfn(set, &data, timeout); + if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { + ret = adtfn(set, &data, timeout, flags); return ip_set_eexist(ret, flags) ? 0 : ret; } @@ -234,7 +227,7 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[], for (; port <= port_to; port++) { data.port = htons(port); - ret = adtfn(set, &data, timeout); + ret = adtfn(set, &data, timeout, flags); if (ret && !ip_set_eexist(ret, flags)) return ret; @@ -378,7 +371,7 @@ hash_netport6_kadt(struct ip_set *set, const struct sk_buff *skb, ip6addrptr(skb, flags & IPSET_DIM_ONE_SRC, &data.ip.in6); ip6_netmask(&data.ip, data.cidr); - return adtfn(set, &data, h->timeout); + return adtfn(set, &data, h->timeout, flags); } static int @@ -390,6 +383,7 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[], struct hash_netport6_elem data = { .cidr = HOST_MASK }; u32 port, port_to; u32 timeout = h->timeout; + bool with_ports = false; int ret; if (unlikely(!tb[IPSET_ATTR_IP] || @@ -418,21 +412,15 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[], if (tb[IPSET_ATTR_PROTO]) { data.proto = nla_get_u8(tb[IPSET_ATTR_PROTO]); + with_ports = ip_set_proto_with_ports(data.proto); if (data.proto == 0) return -IPSET_ERR_INVALID_PROTO; } else return -IPSET_ERR_MISSING_PROTO; - switch (data.proto) { - case IPPROTO_UDP: - case IPPROTO_TCP: - case IPPROTO_ICMPV6: - break; - default: + if (!(with_ports || data.proto == IPPROTO_ICMPV6)) data.port = 0; - break; - } if (tb[IPSET_ATTR_TIMEOUT]) { if (!with_timeout(h->timeout)) @@ -440,10 +428,8 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[], timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); } - if (adt == IPSET_TEST || - !(data.proto == IPPROTO_TCP || data.proto == IPPROTO_UDP) || - !tb[IPSET_ATTR_PORT_TO]) { - ret = adtfn(set, &data, timeout); + if (adt == IPSET_TEST || !with_ports || !tb[IPSET_ATTR_PORT_TO]) { + ret = adtfn(set, &data, timeout, flags); return ip_set_eexist(ret, flags) ? 0 : ret; } @@ -454,7 +440,7 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[], for (; port <= port_to; port++) { data.port = htons(port); - ret = adtfn(set, &data, timeout); + ret = adtfn(set, &data, timeout, flags); if (ret && !ip_set_eexist(ret, flags)) return ret; @@ -540,7 +526,7 @@ static struct ip_set_type hash_netport_type __read_mostly = { .features = IPSET_TYPE_IP | IPSET_TYPE_PORT, .dimension = IPSET_DIM_TWO, .family = AF_UNSPEC, - .revision = 0, + .revision = 1, .create = hash_netport_create, .create_policy = { [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, diff --git a/extensions/ipset-6/ip_set_list_set.c b/extensions/ipset-6/ip_set_list_set.c index 7fc98ff..c3643a0 100644 --- a/extensions/ipset-6/ip_set_list_set.c +++ b/extensions/ipset-6/ip_set_list_set.c @@ -43,14 +43,19 @@ struct list_set { static inline struct set_elem * list_set_elem(const struct list_set *map, u32 id) { - return (struct set_elem *)((char *)map->members + id * map->dsize); + return (struct set_elem *)((void *)map->members + id * map->dsize); +} + +static inline struct set_telem * +list_set_telem(const struct list_set *map, u32 id) +{ + return (struct set_telem *)((void *)map->members + id * map->dsize); } static inline bool list_set_timeout(const struct list_set *map, u32 id) { - const struct set_telem *elem = - (const struct set_telem *) list_set_elem(map, id); + const struct set_telem *elem = list_set_telem(map, id); return ip_set_timeout_test(elem->timeout); } @@ -58,19 +63,11 @@ list_set_timeout(const struct list_set *map, u32 id) static inline bool list_set_expired(const struct list_set *map, u32 id) { - const struct set_telem *elem = - (const struct set_telem *) list_set_elem(map, id); + const struct set_telem *elem = list_set_telem(map, id); return ip_set_timeout_expired(elem->timeout); } -static inline int -list_set_exist(const struct set_telem *elem) -{ - return elem->id != IPSET_INVALID_ID && - !ip_set_timeout_expired(elem->timeout); -} - /* Set list without and with timeout */ static int @@ -112,15 +109,28 @@ list_set_kadt(struct ip_set *set, const struct sk_buff *skb, } static bool -next_id_eq(const struct list_set *map, u32 i, ip_set_id_t id) +id_eq(const struct list_set *map, u32 i, ip_set_id_t id) { const struct set_elem *elem; - if (i + 1 < map->size) { - elem = list_set_elem(map, i + 1); + if (i < map->size) { + elem = list_set_elem(map, i); + return elem->id == id; + } + + return 0; +} + +static bool +id_eq_timeout(const struct list_set *map, u32 i, ip_set_id_t id) +{ + const struct set_elem *elem; + + if (i < map->size) { + elem = list_set_elem(map, i); return !!(elem->id == id && !(with_timeout(map->timeout) && - list_set_expired(map, i + 1))); + list_set_expired(map, i))); } return 0; @@ -146,11 +156,11 @@ list_elem_tadd(struct list_set *map, u32 i, ip_set_id_t id, struct set_telem *e; for (; i < map->size; i++) { - e = (struct set_telem *)list_set_elem(map, i); + e = list_set_telem(map, i); swap(e->id, id); + swap(e->timeout, timeout); if (e->id == IPSET_INVALID_ID) break; - swap(e->timeout, timeout); } } @@ -164,7 +174,7 @@ list_set_add(struct list_set *map, u32 i, ip_set_id_t id, /* Last element replaced: e.g. add new,before,last */ ip_set_put_byindex(e->id); if (with_timeout(map->timeout)) - list_elem_tadd(map, i, id, timeout); + list_elem_tadd(map, i, id, ip_set_timeout_set(timeout)); else list_elem_add(map, i, id); @@ -172,11 +182,11 @@ list_set_add(struct list_set *map, u32 i, ip_set_id_t id, } static int -list_set_del(struct list_set *map, ip_set_id_t id, u32 i) +list_set_del(struct list_set *map, u32 i) { struct set_elem *a = list_set_elem(map, i), *b; - ip_set_put_byindex(id); + ip_set_put_byindex(a->id); for (; i < map->size - 1; i++) { b = list_set_elem(map, i + 1); @@ -193,12 +203,26 @@ list_set_del(struct list_set *map, ip_set_id_t id, u32 i) return 0; } +static void +cleanup_entries(struct list_set *map) +{ + struct set_telem *e; + u32 i; + + for (i = 0; i < map->size; i++) { + e = list_set_telem(map, i); + if (e->id != IPSET_INVALID_ID && list_set_expired(map, i)) + list_set_del(map, i); + } +} + static int list_set_uadt(struct ip_set *set, struct nlattr *tb[], enum ipset_adt adt, u32 *lineno, u32 flags) { struct list_set *map = set->data; bool with_timeout = with_timeout(map->timeout); + bool flag_exist = flags & IPSET_FLAG_EXIST; int before = 0; u32 timeout = map->timeout; ip_set_id_t id, refid = IPSET_INVALID_ID; @@ -251,6 +275,8 @@ list_set_uadt(struct ip_set *set, struct nlattr *tb[], } timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); } + if (with_timeout && adt != IPSET_TEST) + cleanup_entries(map); switch (adt) { case IPSET_TEST: @@ -262,22 +288,37 @@ list_set_uadt(struct ip_set *set, struct nlattr *tb[], else if (with_timeout && list_set_expired(map, i)) continue; else if (before > 0 && elem->id == id) - ret = next_id_eq(map, i, refid); + ret = id_eq_timeout(map, i + 1, refid); else if (before < 0 && elem->id == refid) - ret = next_id_eq(map, i, id); + ret = id_eq_timeout(map, i + 1, id); else if (before == 0 && elem->id == id) ret = 1; } break; case IPSET_ADD: - for (i = 0; i < map->size && !ret; i++) { + for (i = 0; i < map->size; i++) { elem = list_set_elem(map, i); - if (elem->id == id && - !(with_timeout && list_set_expired(map, i))) + if (elem->id != id) + continue; + if (!(with_timeout && flag_exist)) { ret = -IPSET_ERR_EXIST; + goto finish; + } else { + struct set_telem *e = list_set_telem(map, i); + + if ((before > 1 && + !id_eq(map, i + 1, refid)) || + (before < 0 && + (i == 0 || !id_eq(map, i - 1, refid)))) { + ret = -IPSET_ERR_EXIST; + goto finish; + } + e->timeout = ip_set_timeout_set(timeout); + ip_set_put_byindex(id); + ret = 0; + goto finish; + } } - if (ret == -IPSET_ERR_EXIST) - break; ret = -IPSET_ERR_LIST_FULL; for (i = 0; i < map->size && ret == -IPSET_ERR_LIST_FULL; i++) { elem = list_set_elem(map, i); @@ -286,9 +327,7 @@ list_set_uadt(struct ip_set *set, struct nlattr *tb[], : list_set_add(map, i, id, timeout); else if (elem->id != refid) continue; - else if (with_timeout && list_set_expired(map, i)) - ret = -IPSET_ERR_REF_EXIST; - else if (before) + else if (before > 0) ret = list_set_add(map, i, id, timeout); else if (i + 1 < map->size) ret = list_set_add(map, i + 1, id, timeout); @@ -302,17 +341,13 @@ list_set_uadt(struct ip_set *set, struct nlattr *tb[], ret = before != 0 ? -IPSET_ERR_REF_EXIST : -IPSET_ERR_EXIST; break; - } else if (with_timeout && list_set_expired(map, i)) - continue; - else if (elem->id == id && - (before == 0 || - (before > 0 && - next_id_eq(map, i, refid)))) - ret = list_set_del(map, id, i); - else if (before < 0 && - elem->id == refid && - next_id_eq(map, i, id)) - ret = list_set_del(map, id, i + 1); + } else if (elem->id == id && + (before == 0 || + (before > 0 && id_eq(map, i + 1, refid)))) + ret = list_set_del(map, i); + else if (elem->id == refid && + before < 0 && id_eq(map, i + 1, id)) + ret = list_set_del(map, i + 1); } break; default: @@ -369,8 +404,7 @@ list_set_head(struct ip_set *set, struct sk_buff *skb) NLA_PUT_NET32(skb, IPSET_ATTR_SIZE, htonl(map->size)); if (with_timeout(map->timeout)) NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout)); - NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, - htonl(atomic_read(&set->ref) - 1)); + NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)); NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, htonl(sizeof(*map) + map->size * map->dsize)); ipset_nest_end(skb, nested); @@ -458,19 +492,10 @@ list_set_gc(unsigned long ul_set) { struct ip_set *set = (struct ip_set *) ul_set; struct list_set *map = set->data; - struct set_telem *e; - u32 i; - /* We run parallel with other readers (test element) - * but adding/deleting new entries is locked out */ - read_lock_bh(&set->lock); - for (i = map->size - 1; i >= 0; i--) { - e = (struct set_telem *) list_set_elem(map, i); - if (e->id != IPSET_INVALID_ID && - list_set_expired(map, i)) - list_set_del(map, e->id, i); - } - read_unlock_bh(&set->lock); + write_lock_bh(&set->lock); + cleanup_entries(map); + write_unlock_bh(&set->lock); map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ; add_timer(&map->gc); diff --git a/extensions/ipset-6/ipset.8 b/extensions/ipset-6/ipset.8 index b9ca8a5..9603ddc 100644 --- a/extensions/ipset-6/ipset.8 +++ b/extensions/ipset-6/ipset.8 @@ -231,6 +231,8 @@ parameter for the \fBcreate\fR command means the default timeout value (in secon for new entries. If a set is created with timeout support, then the same \fBtimeout\fR option can be used to specify non\-default timeout values when adding entries. Zero timeout value means the entry is added permanent to the set. +The timeout value of already added elements can be changed by readding the element +using the \fB\-exist\fR option. .SS bitmap:ip The \fBbitmap:ip\fR set type uses a memory range to store either IPv4 host (default) or IPv4 network addresses. A \fBbitmap:ip\fR type of set can store up @@ -330,6 +332,9 @@ Mandatory options to use when creating a \fBbitmap:port\fR type of set: \fBrange\fP \fIfromport\fP\-\fItoport\fR Create the set from the specified inclusive port range. .PP +The \fBset\fR match and \fBSET\fR target netfilter kernel modules interpret +the stored numbers as TCP or UDP port numbers. +.PP Examples: .IP ipset create foo bitmap:port range 0\-1024 @@ -380,9 +385,9 @@ a range or a network: .PP Examples: .IP -ipset create foo hash:ip netmask 24 +ipset create foo hash:ip netmask 30 .IP -ipset add foo 192.168.1.1\-192.168.1.2 +ipset add foo 192.168.1.0/24 .IP ipset test foo 192.168.1.2 .SS hash:net @@ -414,8 +419,10 @@ correct value. The maximal number of elements which can be stored in the set, default 65536. .PP When adding/deleting/testing entries, if the cidr prefix parameter is not specified, -then the host prefix value is assumed. When adding/deleting entries, overlapping -elements are not checked. +then the host prefix value is assumed. When adding/deleting entries, the exact +element is added/deleted and overlapping elements are not checked by the kernel. +When testing entries, if a host address is tested, then the kernel tries to match +the host address in the networks added to the set and reports the result accordingly. .PP From the \fBset\fR netfilter match point of view the searching for a match always starts from the smallest size of netblock (most specific @@ -431,7 +438,7 @@ Examples: .IP ipset create foo hash:net .IP -ipset add foo 192.168.0/24 +ipset add foo 192.168.0.0/24 .IP ipset add foo 10.1.0.0/16 .IP @@ -481,8 +488,8 @@ TCP port or range of ports expressed in TCP portname identifiers from /etc/servi \fIportnumber[\-portnumber]\fR TCP port or range of ports expressed in TCP port numbers .TP -\fBtcp\fR|\fBudp\fR:\fIportname\fR|\fIportnumber\fR[\-\fIportname\fR|\fIportnumber\fR] -TCP or UDP port or port range expressed in port name(s) or port number(s) +\fBtcp\fR|\fBsctp\fR|\fBudp\fR|\fBudplite\fR:\fIportname\fR|\fIportnumber\fR[\-\fIportname\fR|\fIportnumber\fR] +TCP, SCTP, UDP or UDPLITE port or port range expressed in port name(s) or port number(s) .TP \fBicmp\fR:\fIcodename\fR|\fItype\fR/\fIcode\fR ICMP codename or type/code. The supported ICMP codename identifiers can always @@ -508,7 +515,7 @@ ipset add foo 192.168.1.0/24,80\-82 .IP ipset add foo 192.168.1.1,udp:53 .IP -ipset add foo 192.168.1.1,ospf:0 +ipset add foo 192.168.1.1,vrrp:0 .IP ipset test foo 192.168.1.1,80 .SS hash:net,port @@ -547,8 +554,10 @@ part of the elements see the description at the \fBhash:ip,port\fR set type. .PP When adding/deleting/testing entries, if the cidr prefix parameter is not specified, -then the host prefix value is assumed. When adding/deleting entries, overlapping -elements are not checked. +then the host prefix value is assumed. When adding/deleting entries, the exact +element is added/deleted and overlapping elements are not checked by the kernel. +When testing entries, if a host address is tested, then the kernel tries to match +the host address in the networks added to the set and reports the result accordingly. .PP From the \fBset\fR netfilter match point of view the searching for a match always starts from the smallest size of netblock (most specific diff --git a/extensions/ipset-6/libipset/parse.c b/extensions/ipset-6/libipset/parse.c index cd1ad32..0c15231 100644 --- a/extensions/ipset-6/libipset/parse.c +++ b/extensions/ipset-6/libipset/parse.c @@ -500,10 +500,9 @@ ipset_parse_proto_port(struct ipset_session *session, p = *(const uint8_t *) ipset_data_get(data, IPSET_OPT_PROTO); switch (p) { case IPPROTO_TCP: - proto = tmp; - tmp = a; - goto parse_port; + case IPPROTO_SCTP: case IPPROTO_UDP: + case IPPROTO_UDPLITE: proto = tmp; tmp = a; goto parse_port; diff --git a/extensions/ipset-6/libipset/print.c b/extensions/ipset-6/libipset/print.c index 5284b0a..66b9c1a 100644 --- a/extensions/ipset-6/libipset/print.c +++ b/extensions/ipset-6/libipset/print.c @@ -585,7 +585,9 @@ ipset_print_proto_port(char *buf, unsigned int len, switch (proto) { case IPPROTO_TCP: + case IPPROTO_SCTP: case IPPROTO_UDP: + case IPPROTO_UDPLITE: break; case IPPROTO_ICMP: return ipset_print_icmp(buf + offset, len, data, diff --git a/extensions/ipset-6/libipset/types.c b/extensions/ipset-6/libipset/types.c index 5eb53c4..402e726 100644 --- a/extensions/ipset-6/libipset/types.c +++ b/extensions/ipset-6/libipset/types.c @@ -198,7 +198,7 @@ create_type_get(struct ipset_session *session) struct ipset_data *data; const char *typename; uint8_t family, tmin = 0, tmax = 0; - const uint8_t *kmin, *kmax; + uint8_t kmin, kmax; int ret; data = ipset_session_data(session); @@ -216,7 +216,7 @@ create_type_get(struct ipset_session *session) && MATCH_FAMILY(t, family)) { if (match == NULL) { match = t; - tmax = t->revision; + tmin = tmax = t->revision; } else if (t->family == match->family) tmin = t->revision; } @@ -240,32 +240,31 @@ create_type_get(struct ipset_session *session) if (ret != 0) return NULL; - kmax = ipset_data_get(data, IPSET_OPT_REVISION); + kmin = kmax = *(const uint8_t *)ipset_data_get(data, IPSET_OPT_REVISION); if (ipset_data_test(data, IPSET_OPT_REVISION_MIN)) - kmin = ipset_data_get(data, IPSET_OPT_REVISION_MIN); - else - kmin = kmax; - if (MAX(tmin, *kmin) > MIN(tmax, *kmax)) { - if (*kmin > tmax) + kmin = *(const uint8_t *)ipset_data_get(data, IPSET_OPT_REVISION_MIN); + + if (MAX(tmin, kmin) > MIN(tmax, kmax)) { + if (kmin > tmax) return ipset_errptr(session, - "Kernel supports %s type with family %s " - "in minimal revision %u while ipset library " - "in maximal revision %u. " - "You need to upgrade your ipset library.", + "Kernel supports %s type, family %s " + "with minimal revision %u while ipset program " + "with maximal revision %u.\n" + "You need to upgrade your ipset program.", typename, family == AF_INET ? "INET" : family == AF_INET6 ? "INET6" : "UNSPEC", - *kmin, tmax); + kmin, tmax); else return ipset_errptr(session, - "Kernel supports %s type with family %s " - "in maximal revision %u while ipset library " - "in minimal revision %u. " + "Kernel supports %s type, family %s " + "with maximal revision %u while ipset program " + "with minimal revision %u.\n" "You need to upgrade your kernel.", typename, family == AF_INET ? "INET" : family == AF_INET6 ? "INET6" : "UNSPEC", - *kmax, tmin); + kmax, tmin); } match->kernel_check = IPSET_KERNEL_OK; diff --git a/extensions/ipset-6/src/ipset_hash_ipport.c b/extensions/ipset-6/src/ipset_hash_ipport.c index 94bda07..3179805 100644 --- a/extensions/ipset-6/src/ipset_hash_ipport.c +++ b/extensions/ipset-6/src/ipset_hash_ipport.c @@ -82,13 +82,13 @@ static const char hash_ipport_usage[] = " IP is a valid IPv4 or IPv6 address (or hostname).\n" " Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n" " is supported for IPv4.\n" -" Adding/deleting multiple elements with TCP/UDP port range\n" -" is supported both for IPv4 and IPv6.\n"; +" Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n" +" port range is supported both for IPv4 and IPv6.\n"; struct ipset_type ipset_hash_ipport0 = { .name = "hash:ip,port", .alias = { "ipporthash", NULL }, - .revision = 0, + .revision = 1, .family = AF_INET46, .dimension = IPSET_DIM_TWO, .elem = { diff --git a/extensions/ipset-6/src/ipset_hash_ipportip.c b/extensions/ipset-6/src/ipset_hash_ipportip.c index cb90152..944ee81 100644 --- a/extensions/ipset-6/src/ipset_hash_ipportip.c +++ b/extensions/ipset-6/src/ipset_hash_ipportip.c @@ -82,13 +82,13 @@ static const char hash_ipportip_usage[] = " IP is a valid IPv4 or IPv6 address (or hostname).\n" " Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n" " in the first IP component is supported for IPv4.\n" -" Adding/deleting multiple elements with TCP/UDP port range\n" -" is supported both for IPv4 and IPv6.\n"; +" Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n" +" port range is supported both for IPv4 and IPv6.\n"; struct ipset_type ipset_hash_ipportip0 = { .name = "hash:ip,port,ip", .alias = { "ipportiphash", NULL }, - .revision = 0, + .revision = 1, .family = AF_INET46, .dimension = IPSET_DIM_THREE, .elem = { diff --git a/extensions/ipset-6/src/ipset_hash_ipportnet.c b/extensions/ipset-6/src/ipset_hash_ipportnet.c index ff3a8ec..bd94d12 100644 --- a/extensions/ipset-6/src/ipset_hash_ipportnet.c +++ b/extensions/ipset-6/src/ipset_hash_ipportnet.c @@ -83,13 +83,13 @@ static const char hash_ipportnet_usage[] = " CIDR is a valid IPv4 or IPv6 CIDR prefix.\n" " Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n" " in the first IP component is supported for IPv4.\n" -" Adding/deleting multiple elements with TCP/UDP port range\n" -" is supported both for IPv4 and IPv6.\n"; +" Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n" +" port range is supported both for IPv4 and IPv6.\n"; struct ipset_type ipset_hash_ipportnet0 = { .name = "hash:ip,port,net", .alias = { "ipportnethash", NULL }, - .revision = 0, + .revision = 1, .family = AF_INET46, .dimension = IPSET_DIM_THREE, .elem = { diff --git a/extensions/ipset-6/src/ipset_hash_netport.c b/extensions/ipset-6/src/ipset_hash_netport.c index 843ef31..8ca77df 100644 --- a/extensions/ipset-6/src/ipset_hash_netport.c +++ b/extensions/ipset-6/src/ipset_hash_netport.c @@ -60,12 +60,13 @@ static const char hash_netport_usage[] = "where depending on the INET family\n" " IP is a valid IPv4 or IPv6 address (or hostname),\n" " CIDR is a valid IPv4 or IPv6 CIDR prefix.\n" -" Adding/deleting multiple elements with TCP/UDP port range supported.\n"; +" Adding/deleting multiple elements with TCP/SCTP/UDP/UDPLITE\n" +" port range is supported both for IPv4 and IPv6.\n"; struct ipset_type ipset_hash_netport0 = { .name = "hash:net,port", .alias = { "netporthash", NULL }, - .revision = 0, + .revision = 1, .family = AF_INET46, .dimension = IPSET_DIM_TWO, .elem = { From 2dc79fe0083a70a285a3cad37779f52e17bf3de1 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 11 Apr 2011 04:03:30 +0200 Subject: [PATCH 4/4] ipset; update to ipset-6.3 (genl) * Handle EAGAIN from autoloading code. * Turn one nfgenmsg site into genlmsg to avoid protocol mismatch --- doc/changelog.txt | 4 ++ .../ipset-6/include/libipset/linux_ip_set.h | 2 +- extensions/ipset-6/ip_set.h | 2 +- extensions/ipset-6/ip_set_bitmap_ipmac.c | 4 ++ extensions/ipset-6/ip_set_core.c | 68 +++++++++++-------- extensions/ipset-6/ip_set_list_set.c | 4 +- extensions/ipset-6/ipset.8 | 7 +- extensions/ipset-6/xt_set.c | 18 ++++- 8 files changed, 73 insertions(+), 36 deletions(-) diff --git a/doc/changelog.txt b/doc/changelog.txt index cf2f0ae..8fedf2c 100644 --- a/doc/changelog.txt +++ b/doc/changelog.txt @@ -21,6 +21,10 @@ Enhancements: * revision reporting fixes - update to ipset 6.2 * list:set timeout variant fixes +- update to ipset 6.3 + * bitmap:ip,mac type requires "src" for MAC, enforce it +- ipset-genl: handle EAGAIN return value emitted from autoloader +- ipset-genl: resolve nfgenmsg remains and fix spurious protocol abort v1.33 (2011-02-02) diff --git a/extensions/ipset-6/include/libipset/linux_ip_set.h b/extensions/ipset-6/include/libipset/linux_ip_set.h index d4b6308..d81a811 100644 --- a/extensions/ipset-6/include/libipset/linux_ip_set.h +++ b/extensions/ipset-6/include/libipset/linux_ip_set.h @@ -12,7 +12,7 @@ */ /* The protocol version */ -#define IPSET_PROTOCOL 60 +#define IPSET_PROTOCOL 6 /* The max length of strings including NUL: set and type identifiers */ #define IPSET_MAXNAMELEN 32 diff --git a/extensions/ipset-6/ip_set.h b/extensions/ipset-6/ip_set.h index 8026f1b..08f59eb 100644 --- a/extensions/ipset-6/ip_set.h +++ b/extensions/ipset-6/ip_set.h @@ -14,7 +14,7 @@ #include /* The protocol version */ -#define IPSET_PROTOCOL 60 +#define IPSET_PROTOCOL 6 /* The max length of strings including NUL: set and type identifiers */ #define IPSET_MAXNAMELEN 32 diff --git a/extensions/ipset-6/ip_set_bitmap_ipmac.c b/extensions/ipset-6/ip_set_bitmap_ipmac.c index 74bca4c..175d871 100644 --- a/extensions/ipset-6/ip_set_bitmap_ipmac.c +++ b/extensions/ipset-6/ip_set_bitmap_ipmac.c @@ -344,6 +344,10 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb, ipset_adtfn adtfn = set->variant->adt[adt]; struct ipmac data; + /* MAC can be src only */ + if (!(flags & IPSET_DIM_TWO_SRC)) + return 0; + data.id = ntohl(ip4addr(skb, flags & IPSET_DIM_ONE_SRC)); if (data.id < map->first_ip || data.id > map->last_ip) return -IPSET_ERR_BITMAP_RANGE; diff --git a/extensions/ipset-6/ip_set_core.c b/extensions/ipset-6/ip_set_core.c index abf1c90..509a87c 100644 --- a/extensions/ipset-6/ip_set_core.c +++ b/extensions/ipset-6/ip_set_core.c @@ -26,6 +26,8 @@ #include #define GENLMSG_DEFAULT_SIZE (NLMSG_DEFAULT_SIZE - GENL_HDRLEN) +struct genlmsg_buf; + static LIST_HEAD(ip_set_type_list); /* all registered set types */ static DEFINE_MUTEX(ip_set_type_mutex); /* protects ip_set_type_list */ static DEFINE_RWLOCK(ip_set_ref_lock); /* protects the set refs */ @@ -82,14 +84,14 @@ find_set_type(const char *name, u8 family, u8 revision) static int try_to_load_type(const char *name) { - nfnl_unlock(); + genl_unlock(); pr_debug("try to load ip_set_%s\n", name); if (request_module("ip_set_%s", name) < 0) { pr_warning("Can't find ip_set type %s\n", name); - nfnl_lock(); + genl_lock(); return -IPSET_ERR_FIND_TYPE; } - nfnl_lock(); + genl_lock(); return -EAGAIN; } @@ -99,8 +101,10 @@ find_set_type_get(const char *name, u8 family, u8 revision, struct ip_set_type **found) { struct ip_set_type *type; + unsigned int retry = 0; int err; +retry: rcu_read_lock(); *found = find_set_type(name, family, revision); if (*found) { @@ -115,7 +119,10 @@ find_set_type_get(const char *name, u8 family, u8 revision, } rcu_read_unlock(); - return try_to_load_type(name); + err = try_to_load_type(name); + if (err == -EAGAIN && retry++ == 0) + goto retry; + return err; unlock: rcu_read_unlock(); @@ -131,7 +138,10 @@ find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max) { struct ip_set_type *type; bool found = false; + unsigned int retry = 0; + int err; +retry: *min = 255; *max = 0; rcu_read_lock(); list_for_each_entry_rcu(type, &ip_set_type_list, list) @@ -147,7 +157,10 @@ find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max) if (found) return 0; - return try_to_load_type(name); + err = try_to_load_type(name); + if (err == -EAGAIN && retry++ == 0) + goto retry; + return err; } #define family_name(f) ((f) == AF_INET ? "inet" : \ @@ -482,9 +495,9 @@ ip_set_nfnl_get(const char *name) struct ip_set *s; ip_set_id_t index; - nfnl_lock(); + genl_lock(); index = ip_set_get_byname(name, &s); - nfnl_unlock(); + genl_unlock(); return index; } @@ -502,12 +515,12 @@ ip_set_nfnl_get_byindex(ip_set_id_t index) if (index > ip_set_max) return IPSET_INVALID_ID; - nfnl_lock(); + genl_lock(); if (ip_set_list[index]) __ip_set_get(index); else index = IPSET_INVALID_ID; - nfnl_unlock(); + genl_unlock(); return index; } @@ -523,9 +536,9 @@ EXPORT_SYMBOL_GPL(ip_set_nfnl_get_byindex); void ip_set_nfnl_put(ip_set_id_t index) { - nfnl_lock(); + genl_lock(); ip_set_put_byindex(index); - nfnl_unlock(); + genl_unlock(); } EXPORT_SYMBOL_GPL(ip_set_nfnl_put); @@ -548,11 +561,11 @@ flag_exist(const struct genlmsghdr *ghdr) return ghdr->reserved & NLM_F_EXCL ? 0 : IPSET_FLAG_EXIST; } -static struct nlmsghdr * +static struct genlmsg_buf * start_msg(struct sk_buff *skb, u32 pid, u32 seq, unsigned int flags, enum ipset_cmd cmd) { - void *nlh; + struct genlmsg_buf *nlh; nlh = genlmsg_put(skb, pid, seq, &ip_set_netlink_subsys, flags, cmd); if (nlh == NULL) @@ -950,10 +963,11 @@ ip_set_dump_done(struct netlink_callback *cb) } static inline void -dump_attrs(void *phdr) +dump_attrs(struct genlmsg_buf *phdr) { const struct nlattr *attr; - const struct nlmsghdr *nlh = phdr - GENL_HDRLEN - NLMSG_HDRLEN; + const struct nlmsghdr *nlh = + (const void *)phdr - GENL_HDRLEN - NLMSG_HDRLEN; int rem; pr_debug("dump nlmsg\n"); @@ -999,14 +1013,14 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb) { ip_set_id_t index = IPSET_INVALID_ID, max; struct ip_set *set = NULL; - struct nlmsghdr *nlh = NULL; + struct genlmsg_buf *nlh = NULL; unsigned int flags = NETLINK_CB(cb->skb).pid ? NLM_F_MULTI : 0; int ret = 0; if (cb->args[0] == DUMP_INIT) { ret = dump_init(cb); if (ret < 0) { - nlh = nlmsg_hdr(cb->skb); + struct nlmsghdr *nlh = nlmsg_hdr(cb->skb); /* We have to create and send the error message * manually :-( */ if (nlh->nlmsg_flags & NLM_F_ACK) @@ -1159,7 +1173,7 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set, struct sk_buff *skb2; struct nlmsgerr *errmsg; size_t payload = sizeof(*errmsg) + nlmsg_len(nlh); - int min_len = NLMSG_SPACE(sizeof(struct nfgenmsg)); + int min_len = NLMSG_SPACE(sizeof(struct genlmsghdr)); struct nlattr *cda[IPSET_ATTR_CMD_MAX+1]; struct nlattr *cmdattr; u32 *errline; @@ -1342,7 +1356,7 @@ ip_set_header(struct sk_buff *skb, struct genl_info *info) struct nlattr *const *attr = info->attrs; const struct nlmsghdr *nlh = info->nlhdr; struct sk_buff *skb2; - struct nlmsghdr *nlh2; + struct genlmsg_buf *nlh2; ip_set_id_t index; int ret = 0; @@ -1355,7 +1369,7 @@ ip_set_header(struct sk_buff *skb, struct genl_info *info) return -ENOENT; set = ip_set_list[index]; - skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + skb2 = genlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (skb2 == NULL) return -ENOMEM; @@ -1377,7 +1391,7 @@ ip_set_header(struct sk_buff *skb, struct genl_info *info) return 0; nla_put_failure: - nlmsg_cancel(skb2, nlh2); + genlmsg_cancel(skb2, nlh2); nlmsg_failure: kfree_skb(skb2); return -EMSGSIZE; @@ -1399,7 +1413,7 @@ ip_set_type(struct sk_buff *skb, struct genl_info *info) const struct nlmsghdr *nlh = info->nlhdr; struct sk_buff *skb2; - void *nlh2; + struct genlmsg_buf *nlh2; u8 family, min, max; const char *typename; int ret = 0; @@ -1458,7 +1472,7 @@ ip_set_protocol(struct sk_buff *skb, struct genl_info *info) const struct nlmsghdr *nlh = info->nlhdr; struct sk_buff *skb2; - void *nlh2; + struct genlmsg_buf *nlh2; int ret = 0; if (unlikely(attr[IPSET_ATTR_PROTOCOL] == NULL)) @@ -1633,9 +1647,9 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len) goto done; } req_get->set.name[IPSET_MAXNAMELEN - 1] = '\0'; - nfnl_lock(); + genl_lock(); req_get->set.index = find_set_id(req_get->set.name); - nfnl_unlock(); + genl_unlock(); goto copy; } case IP_SET_OP_GET_BYINDEX: { @@ -1646,12 +1660,12 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len) ret = -EINVAL; goto done; } - nfnl_lock(); + genl_lock(); strncpy(req_get->set.name, ip_set_list[req_get->set.index] ? ip_set_list[req_get->set.index]->name : "", IPSET_MAXNAMELEN); - nfnl_unlock(); + genl_unlock(); goto copy; } default: diff --git a/extensions/ipset-6/ip_set_list_set.c b/extensions/ipset-6/ip_set_list_set.c index c3643a0..e15f819 100644 --- a/extensions/ipset-6/ip_set_list_set.c +++ b/extensions/ipset-6/ip_set_list_set.c @@ -310,8 +310,8 @@ list_set_uadt(struct ip_set *set, struct nlattr *tb[], !id_eq(map, i + 1, refid)) || (before < 0 && (i == 0 || !id_eq(map, i - 1, refid)))) { - ret = -IPSET_ERR_EXIST; - goto finish; + ret = -IPSET_ERR_EXIST; + goto finish; } e->timeout = ip_set_timeout_set(timeout); ip_set_put_byindex(id); diff --git a/extensions/ipset-6/ipset.8 b/extensions/ipset-6/ipset.8 index 9603ddc..d9e5ff8 100644 --- a/extensions/ipset-6/ipset.8 +++ b/extensions/ipset-6/ipset.8 @@ -302,9 +302,10 @@ matched by the kernel, it will automatically fill out the missing MAC address wi source MAC address from the packet. If the entry was specified with a timeout value, the timer starts off when the IP and MAC address pair is complete. .PP -Please note, the \fBset\fR match and \fBSET\fR target netfilter kernel modules -\fBalways\fR use the source MAC address from the packet to match, add or delete -entries from a \fBbitmap:ip,mac\fR type of set. +The \fBbitmap:ip,mac\fR type of sets require two \fBsrc/dst\fR parameters of +the \fBset\fR match and \fBSET\fR target netfilter kernel modules and the second +one must be \fBsrc\fR to match, add or delete entries because the \fBset\fR match +and \fBSET\fR target have access to the source MAC address only. .PP Examples: .IP diff --git a/extensions/ipset-6/xt_set.c b/extensions/ipset-6/xt_set.c index f2a9088..93de81d 100644 --- a/extensions/ipset-6/xt_set.c +++ b/extensions/ipset-6/xt_set.c @@ -115,6 +115,7 @@ set_match_v0_checkentry(const struct xt_mtchk_param *par) if (info->match_set.u.flags[IPSET_DIM_MAX-1] != 0) { pr_warning("Protocol error: set match dimension " "is over the limit!\n"); + ip_set_nfnl_put(info->match_set.index); return CHECK_FAIL(-ERANGE); /* error */ } @@ -179,6 +180,8 @@ set_target_v0_checkentry(const struct xt_tgchk_param *par) if (index == IPSET_INVALID_ID) { pr_warning("Cannot find del_set index %u as target\n", info->del_set.index); + if (info->add_set.index != IPSET_INVALID_ID) + ip_set_nfnl_put(info->add_set.index); return CHECK_FAIL(-ENOENT); /* error */ } } @@ -186,6 +189,10 @@ set_target_v0_checkentry(const struct xt_tgchk_param *par) info->del_set.u.flags[IPSET_DIM_MAX-1] != 0) { pr_warning("Protocol error: SET target dimension " "is over the limit!\n"); + if (info->add_set.index != IPSET_INVALID_ID) + ip_set_nfnl_put(info->add_set.index); + if (info->del_set.index != IPSET_INVALID_ID) + ip_set_nfnl_put(info->del_set.index); return CHECK_FAIL(-ERANGE); /* error */ } @@ -246,6 +253,7 @@ set_match_checkentry(const struct xt_mtchk_param *par) if (info->match_set.dim > IPSET_DIM_MAX) { pr_warning("Protocol error: set match dimension " "is over the limit!\n"); + ip_set_nfnl_put(info->match_set.index); return CHECK_FAIL(-ERANGE); /* error */ } @@ -278,7 +286,7 @@ set_target(struct sk_buff *skb, const struct xt_action_param *par) if (info->del_set.index != IPSET_INVALID_ID) ip_set_del(info->del_set.index, skb, par->family, - info->add_set.dim, + info->del_set.dim, info->del_set.flags); return XT_CONTINUE; @@ -309,13 +317,19 @@ set_target_checkentry(const struct xt_tgchk_param *par) if (index == IPSET_INVALID_ID) { pr_warning("Cannot find del_set index %u as target\n", info->del_set.index); + if (info->add_set.index != IPSET_INVALID_ID) + ip_set_nfnl_put(info->add_set.index); return CHECK_FAIL(-ENOENT); /* error */ } } if (info->add_set.dim > IPSET_DIM_MAX || - info->del_set.flags > IPSET_DIM_MAX) { + info->del_set.dim > IPSET_DIM_MAX) { pr_warning("Protocol error: SET target dimension " "is over the limit!\n"); + if (info->add_set.index != IPSET_INVALID_ID) + ip_set_nfnl_put(info->add_set.index); + if (info->del_set.index != IPSET_INVALID_ID) + ip_set_nfnl_put(info->del_set.index); return CHECK_FAIL(-ERANGE); /* error */ }