As scheduled, perform the removal of ipset from the tree.
- CONFIG_CONNECTOR y/m if you wish to receive userspace
notifications from pknock through netlink/connector
-Compilation of ipset-genl-6.x is disabled by default. It has
-additional requirements.
-
- * libmnl
- * Linux kernel >= 2.6.35
-
Selecting extensions
====================
Included in this package
========================
-- ipset 6.10-genl
- xt_ACCOUNT 1.16, libxt_ACCOUNT 1.3
[AC_MSG_ERROR([You need to have linux/netfilter/x_tables.h, see INSTALL file for details])])
PKG_CHECK_MODULES([libxtables], [xtables >= 1.4.5])
xtlibdir="$(pkg-config --variable=xtlibdir xtables)"
-PKG_CHECK_MODULES([libmnl], [libmnl >= 1], [:], [:])
AC_ARG_WITH([xtlibdir],
AS_HELP_STRING([--with-xtlibdir=PATH],
AC_SUBST([xtlibdir])
AC_CONFIG_FILES([Makefile Makefile.iptrules Makefile.mans geoip/Makefile
extensions/Makefile extensions/ACCOUNT/Makefile
- extensions/ipset-6/Makefile
extensions/pknock/Makefile])
AC_OUTPUT
- compat_xtables: fixed mistranslation of checkentry return values
(affected kernels < 2.6.23)
- xt_SYSRQ: fix compile error when crypto is turned off
+Changes:
+- ipset6-genl has been dropped from the tree;
+ the libmnl build-time dependency is thus no longer needed
Enhancements:
- Support for Linux 3.3, 3.4
obj-${build_geoip} += xt_geoip.o
obj-${build_iface} += xt_iface.o
obj-${build_ipp2p} += xt_ipp2p.o
-obj-${build_ipset6} += ipset-6/
obj-${build_ipv4options} += xt_ipv4options.o
obj-${build_length2} += xt_length2.o
obj-${build_lscan} += xt_lscan.o
obj-${build_geoip} += libxt_geoip.so
obj-${build_iface} += libxt_iface.so
obj-${build_ipp2p} += libxt_ipp2p.so
-obj-${build_ipset6} += ipset-6/
obj-${build_ipv4options} += libxt_ipv4options.so
obj-${build_length2} += libxt_length2.so
obj-${build_lscan} += libxt_lscan.so
+++ /dev/null
-# -*- Makefile -*-
-
-obj-m += xt_set.o
-obj-m += ip_set.o ip_set_bitmap_ip.o ip_set_bitmap_ipmac.o
-obj-m += ip_set_bitmap_port.o ip_set_hash_ip.o ip_set_hash_ipport.o
-obj-m += ip_set_hash_ipportip.o ip_set_hash_ipportnet.o ip_set_hash_net.o
-obj-m += ip_set_hash_netiface.o ip_set_hash_netport.o ip_set_list_set.o
-
-ip_set-y := ip_set_core.o ip_set_getport.o pfxlen.o
-
-EXTRA_CFLAGS += -DLCONFIG_IP_SET_MAX=256
+++ /dev/null
-# -*- Makefile -*-
-
-AM_CPPFLAGS = -I${srcdir}/include -DNDEBUG
-AM_CFLAGS = ${regular_CFLAGS} ${libmnl_CFLAGS}
-
-include ../../Makefile.extra
-
-lib_LTLIBRARIES = libipset.la
-libipset_la_SOURCES = libipset/data.c libipset/icmp.c libipset/icmpv6.c \
- libipset/mnl.c libipset/parse.c libipset/print.c \
- libipset/session.c libipset/types.c libipset/errcode.c
-libipset_la_LIBADD = ${libmnl_LIBS}
-libipset_la_LDFLAGS = -version-info 1:0:0
-
-sbin_PROGRAMS = ipset
-ipset_SOURCES = src/ipset.c src/ui.c src/ipset_bitmap_ip.c \
- src/ipset_bitmap_ipmac.c src/ipset_bitmap_port.c \
- src/ipset_hash_ip.c src/ipset_hash_ipport.c \
- src/ipset_hash_ipportip.c src/ipset_hash_ipportnet.c \
- src/ipset_hash_net.c src/ipset_hash_netiface.c \
- src/ipset_hash_netport.c \
- src/ipset_list_set.c
-ipset_LDADD = libipset.la
-
-man_MANS = src/ipset.8
+++ /dev/null
-# -*- Makefile -*-
-
+++ /dev/null
-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.
+++ /dev/null
-5.4.1-genl
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#ifndef LIBIPSET_DATA_H
-#define LIBIPSET_DATA_H
-
-#include <stdbool.h> /* bool */
-#include <libipset/nf_inet_addr.h> /* union nf_inet_addr */
-
-/* Data options */
-enum ipset_opt {
- IPSET_OPT_NONE = 0,
- /* Common ones */
- IPSET_SETNAME,
- IPSET_OPT_TYPENAME,
- IPSET_OPT_FAMILY,
- /* CADT options */
- IPSET_OPT_IP,
- IPSET_OPT_IP_FROM = IPSET_OPT_IP,
- IPSET_OPT_IP_TO,
- IPSET_OPT_CIDR,
- IPSET_OPT_PORT,
- IPSET_OPT_PORT_FROM = IPSET_OPT_PORT,
- IPSET_OPT_PORT_TO,
- IPSET_OPT_TIMEOUT,
- /* Create-specific options */
- IPSET_OPT_GC,
- IPSET_OPT_HASHSIZE,
- IPSET_OPT_MAXELEM,
- IPSET_OPT_NETMASK,
- IPSET_OPT_PROBES,
- IPSET_OPT_RESIZE,
- IPSET_OPT_SIZE,
- /* Create-specific options, filled out by the kernel */
- IPSET_OPT_ELEMENTS,
- IPSET_OPT_REFERENCES,
- IPSET_OPT_MEMSIZE,
- /* ADT-specific options */
- IPSET_OPT_ETHER,
- IPSET_OPT_NAME,
- IPSET_OPT_NAMEREF,
- IPSET_OPT_IP2,
- IPSET_OPT_CIDR2,
- IPSET_OPT_IP2_TO,
- IPSET_OPT_PROTO,
- IPSET_OPT_IFACE,
- /* Swap/rename to */
- IPSET_OPT_SETNAME2,
- /* Flags */
- IPSET_OPT_EXIST,
- IPSET_OPT_BEFORE,
- IPSET_OPT_PHYSDEV,
- /* Internal options */
- IPSET_OPT_FLAGS = 48, /* IPSET_FLAG_EXIST| */
- IPSET_OPT_CADT_FLAGS, /* IPSET_FLAG_BEFORE| */
- IPSET_OPT_ELEM,
- IPSET_OPT_TYPE,
- IPSET_OPT_LINENO,
- IPSET_OPT_REVISION,
- IPSET_OPT_REVISION_MIN,
- IPSET_OPT_MAX,
-};
-
-#define IPSET_FLAG(opt) (1LL << (opt))
-#define IPSET_FLAGS_ALL (~0LL)
-
-#define IPSET_CREATE_FLAGS \
- (IPSET_FLAG(IPSET_OPT_FAMILY) \
- | IPSET_FLAG(IPSET_OPT_TYPENAME)\
- | IPSET_FLAG(IPSET_OPT_TYPE) \
- | IPSET_FLAG(IPSET_OPT_IP) \
- | IPSET_FLAG(IPSET_OPT_IP_TO) \
- | IPSET_FLAG(IPSET_OPT_CIDR) \
- | IPSET_FLAG(IPSET_OPT_PORT) \
- | IPSET_FLAG(IPSET_OPT_PORT_TO) \
- | IPSET_FLAG(IPSET_OPT_TIMEOUT) \
- | IPSET_FLAG(IPSET_OPT_GC) \
- | IPSET_FLAG(IPSET_OPT_HASHSIZE)\
- | IPSET_FLAG(IPSET_OPT_MAXELEM) \
- | IPSET_FLAG(IPSET_OPT_NETMASK) \
- | IPSET_FLAG(IPSET_OPT_PROBES) \
- | IPSET_FLAG(IPSET_OPT_RESIZE) \
- | IPSET_FLAG(IPSET_OPT_SIZE))
-
-#define IPSET_ADT_FLAGS \
- (IPSET_FLAG(IPSET_OPT_IP) \
- | IPSET_FLAG(IPSET_OPT_IP_TO) \
- | IPSET_FLAG(IPSET_OPT_CIDR) \
- | IPSET_FLAG(IPSET_OPT_PORT) \
- | IPSET_FLAG(IPSET_OPT_PORT_TO) \
- | IPSET_FLAG(IPSET_OPT_TIMEOUT) \
- | IPSET_FLAG(IPSET_OPT_ETHER) \
- | IPSET_FLAG(IPSET_OPT_NAME) \
- | IPSET_FLAG(IPSET_OPT_NAMEREF) \
- | IPSET_FLAG(IPSET_OPT_IP2) \
- | IPSET_FLAG(IPSET_OPT_CIDR2) \
- | IPSET_FLAG(IPSET_OPT_PROTO) \
- | IPSET_FLAG(IPSET_OPT_IFACE) \
- | IPSET_FLAG(IPSET_OPT_CADT_FLAGS)\
- | IPSET_FLAG(IPSET_OPT_BEFORE) \
- | IPSET_FLAG(IPSET_OPT_PHYSDEV))
-
-struct ipset_data;
-
-extern void ipset_strlcpy(char *dst, const char *src, size_t len);
-extern bool ipset_data_flags_test(const struct ipset_data *data,
- uint64_t flags);
-extern void ipset_data_flags_set(struct ipset_data *data, uint64_t flags);
-extern void ipset_data_flags_unset(struct ipset_data *data, uint64_t flags);
-extern bool ipset_data_ignored(struct ipset_data *data, enum ipset_opt opt);
-
-extern int ipset_data_set(struct ipset_data *data, enum ipset_opt opt,
- const void *value);
-extern const void *ipset_data_get(const struct ipset_data *data,
- enum ipset_opt opt);
-
-static inline bool
-ipset_data_test(const struct ipset_data *data, enum ipset_opt opt)
-{
- return ipset_data_flags_test(data, IPSET_FLAG(opt));
-}
-
-/* Shortcuts */
-extern const char *ipset_data_setname(const struct ipset_data *data);
-extern uint8_t ipset_data_family(const struct ipset_data *data);
-extern uint8_t ipset_data_cidr(const struct ipset_data *data);
-extern uint64_t ipset_data_flags(const struct ipset_data *data);
-
-extern void ipset_data_reset(struct ipset_data *data);
-extern struct ipset_data *ipset_data_init(void);
-extern void ipset_data_fini(struct ipset_data *data);
-
-extern size_t ipset_data_sizeof(enum ipset_opt opt, uint8_t family);
-
-#endif /* LIBIPSET_DATA_H */
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#ifndef LIBIPSET_DEBUG_H
-#define LIBIPSET_DEBUG_H
-
-#ifdef IPSET_DEBUG
-#include <stdio.h>
-#include <sys/socket.h>
-#include <linux/netlink.h>
-#define D(fmt, args...) \
- fprintf(stderr, "%s: %s: " fmt "\n", __FILE__, __func__ , ## args)
-#define IF_D(test, fmt, args...) \
- if (test) \
- D(fmt , ## args)
-
-static inline void
-dump_nla(struct nlattr *nla[], int maxlen)
-{
- int i;
- for (i = 0; i < maxlen; i++)
- D("nla[%u] does%s exist", i, nla[i] ? "" : " NOT");
-}
-#else
-#define D(fmt, args...)
-#define IF_D(test, fmt, args...)
-#define dump_nla(nla, maxlen)
-#endif
-
-#endif /* LIBIPSET_DEBUG_H */
+++ /dev/null
-/* Copyright 2007-2008 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#ifndef LIBIPSET_ERRCODE_H
-#define LIBIPSET_ERRCODE_H
-
-#include <libipset/linux_ip_set.h> /* enum ipset_cmd */
-
-struct ipset_session;
-
-/* Kernel error code to message table */
-struct ipset_errcode_table {
- int errcode; /* error code returned by the kernel */
- enum ipset_cmd cmd; /* issued command */
- const char *message; /* error message the code translated to */
-};
-
-extern int ipset_errcode(struct ipset_session *session, enum ipset_cmd cmd,
- int errcode);
-
-#endif /* LIBIPSET_ERRCODE_H */
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#ifndef LIBIPSET_ICMP_H
-#define LIBIPSET_ICMP_H
-
-#include <stdint.h> /* uintxx_t */
-
-extern const char *id_to_icmp(uint8_t id);
-extern const char *icmp_to_name(uint8_t type, uint8_t code);
-extern int name_to_icmp(const char *str, uint16_t *typecode);
-
-#endif /* LIBIPSET_ICMP_H */
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#ifndef LIBIPSET_ICMPV6_H
-#define LIBIPSET_ICMPV6_H
-
-#include <stdint.h> /* uintxx_t */
-
-extern const char *id_to_icmpv6(uint8_t id);
-extern const char *icmpv6_to_name(uint8_t type, uint8_t code);
-extern int name_to_icmpv6(const char *str, uint16_t *typecode);
-
-#endif /* LIBIPSET_ICMPV6_H */
+++ /dev/null
-#ifndef _IP_SET_H
-#define _IP_SET_H
-
-/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
- * Patrick Schaaf <bof@bof.de>
- * Martin Josefsson <gandalf@wlug.westbo.se>
- * Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/types.h>
-
-/* The protocol version */
-#define IPSET_PROTOCOL 0x60
-
-/* The max length of strings including NUL: set and type identifiers */
-#define IPSET_MAXNAMELEN 32
-
-/* Message types and commands */
-enum ipset_cmd {
- IPSET_CMD_NONE,
- IPSET_CMD_PROTOCOL, /* 1: Return protocol version */
- IPSET_CMD_CREATE, /* 2: Create a new (empty) set */
- IPSET_CMD_DESTROY, /* 3: Destroy a (empty) set */
- IPSET_CMD_FLUSH, /* 4: Remove all elements from a set */
- IPSET_CMD_RENAME, /* 5: Rename a set */
- IPSET_CMD_SWAP, /* 6: Swap two sets */
- IPSET_CMD_LIST, /* 7: List sets */
- IPSET_CMD_SAVE, /* 8: Save sets */
- IPSET_CMD_ADD, /* 9: Add an element to a set */
- IPSET_CMD_DEL, /* 10: Delete an element from a set */
- IPSET_CMD_TEST, /* 11: Test an element in a set */
- IPSET_CMD_HEADER, /* 12: Get set header data only */
- IPSET_CMD_TYPE, /* 13: Get set type */
- IPSET_MSG_MAX, /* Netlink message commands */
-
- /* Commands in userspace: */
- IPSET_CMD_RESTORE = IPSET_MSG_MAX, /* 14: Enter restore mode */
- IPSET_CMD_HELP, /* 15: Get help */
- IPSET_CMD_VERSION, /* 16: Get program version */
- IPSET_CMD_QUIT, /* 17: Quit from interactive mode */
-
- IPSET_CMD_MAX,
-
- IPSET_CMD_COMMIT = IPSET_CMD_MAX, /* 18: Commit buffered commands */
-};
-
-/* Attributes at command level */
-enum {
- IPSET_ATTR_UNSPEC,
- IPSET_ATTR_PROTOCOL, /* 1: Protocol version */
- IPSET_ATTR_SETNAME, /* 2: Name of the set */
- IPSET_ATTR_TYPENAME, /* 3: Typename */
- IPSET_ATTR_SETNAME2 = IPSET_ATTR_TYPENAME, /* Setname at rename/swap */
- IPSET_ATTR_REVISION, /* 4: Settype revision */
- IPSET_ATTR_FAMILY, /* 5: Settype family */
- IPSET_ATTR_FLAGS, /* 6: Flags at command level */
- IPSET_ATTR_DATA, /* 7: Nested attributes */
- IPSET_ATTR_ADT, /* 8: Multiple data containers */
- IPSET_ATTR_LINENO, /* 9: Restore lineno */
- IPSET_ATTR_PROTOCOL_MIN, /* 10: Minimal supported version number */
- IPSET_ATTR_REVISION_MIN = IPSET_ATTR_PROTOCOL_MIN, /* type rev min */
- __IPSET_ATTR_CMD_MAX,
-};
-#define IPSET_ATTR_CMD_MAX (__IPSET_ATTR_CMD_MAX - 1)
-
-/* CADT specific attributes */
-enum {
- IPSET_ATTR_IP = IPSET_ATTR_UNSPEC + 1,
- IPSET_ATTR_IP_FROM = IPSET_ATTR_IP,
- IPSET_ATTR_IP_TO, /* 2 */
- IPSET_ATTR_CIDR, /* 3 */
- IPSET_ATTR_PORT, /* 4 */
- IPSET_ATTR_PORT_FROM = IPSET_ATTR_PORT,
- IPSET_ATTR_PORT_TO, /* 5 */
- IPSET_ATTR_TIMEOUT, /* 6 */
- IPSET_ATTR_PROTO, /* 7 */
- IPSET_ATTR_CADT_FLAGS, /* 8 */
- IPSET_ATTR_CADT_LINENO = IPSET_ATTR_LINENO, /* 9 */
- /* Reserve empty slots */
- IPSET_ATTR_CADT_MAX = 16,
- /* Create-only specific attributes */
- IPSET_ATTR_GC,
- IPSET_ATTR_HASHSIZE,
- IPSET_ATTR_MAXELEM,
- IPSET_ATTR_NETMASK,
- IPSET_ATTR_PROBES,
- IPSET_ATTR_RESIZE,
- IPSET_ATTR_SIZE,
- /* Kernel-only */
- IPSET_ATTR_ELEMENTS,
- IPSET_ATTR_REFERENCES,
- IPSET_ATTR_MEMSIZE,
-
- __IPSET_ATTR_CREATE_MAX,
-};
-#define IPSET_ATTR_CREATE_MAX (__IPSET_ATTR_CREATE_MAX - 1)
-
-/* ADT specific attributes */
-enum {
- IPSET_ATTR_ETHER = IPSET_ATTR_CADT_MAX + 1,
- IPSET_ATTR_NAME,
- IPSET_ATTR_NAMEREF,
- IPSET_ATTR_IP2,
- IPSET_ATTR_CIDR2,
- IPSET_ATTR_IP2_TO,
- IPSET_ATTR_IFACE,
- __IPSET_ATTR_ADT_MAX,
-};
-#define IPSET_ATTR_ADT_MAX (__IPSET_ATTR_ADT_MAX - 1)
-
-/* IP specific attributes */
-enum {
- IPSET_ATTR_IPADDR_IPV4 = IPSET_ATTR_UNSPEC + 1,
- IPSET_ATTR_IPADDR_IPV6,
- __IPSET_ATTR_IPADDR_MAX,
-};
-#define IPSET_ATTR_IPADDR_MAX (__IPSET_ATTR_IPADDR_MAX - 1)
-
-/* Error codes */
-enum ipset_errno {
- IPSET_ERR_PRIVATE = 4096,
- IPSET_ERR_PROTOCOL,
- IPSET_ERR_FIND_TYPE,
- IPSET_ERR_MAX_SETS,
- IPSET_ERR_BUSY,
- IPSET_ERR_EXIST_SETNAME2,
- IPSET_ERR_TYPE_MISMATCH,
- IPSET_ERR_EXIST,
- IPSET_ERR_INVALID_CIDR,
- IPSET_ERR_INVALID_NETMASK,
- IPSET_ERR_INVALID_FAMILY,
- IPSET_ERR_TIMEOUT,
- IPSET_ERR_REFERENCED,
- IPSET_ERR_IPADDR_IPV4,
- IPSET_ERR_IPADDR_IPV6,
-
- /* Type specific error codes */
- IPSET_ERR_TYPE_SPECIFIC = 4352,
-};
-
-/* Flags at command level */
-enum ipset_cmd_flags {
- IPSET_FLAG_BIT_EXIST = 0,
- IPSET_FLAG_EXIST = (1 << IPSET_FLAG_BIT_EXIST),
- IPSET_FLAG_BIT_LIST_SETNAME = 1,
- IPSET_FLAG_LIST_SETNAME = (1 << IPSET_FLAG_BIT_LIST_SETNAME),
- IPSET_FLAG_BIT_LIST_HEADER = 2,
- IPSET_FLAG_LIST_HEADER = (1 << IPSET_FLAG_BIT_LIST_HEADER),
-};
-
-/* Flags at CADT attribute level */
-enum ipset_cadt_flags {
- IPSET_FLAG_BIT_BEFORE = 0,
- IPSET_FLAG_BEFORE = (1 << IPSET_FLAG_BIT_BEFORE),
- IPSET_FLAG_BIT_PHYSDEV = 1,
- IPSET_FLAG_PHYSDEV = (1 << IPSET_FLAG_BIT_PHYSDEV),
-};
-
-/* Commands with settype-specific attributes */
-enum ipset_adt {
- IPSET_ADD,
- IPSET_DEL,
- IPSET_TEST,
- IPSET_ADT_MAX,
- IPSET_CREATE = IPSET_ADT_MAX,
- IPSET_CADT_MAX,
-};
-
-/* Sets are identified by an index in kernel space. Tweak with ip_set_id_t
- * and IPSET_INVALID_ID if you want to increase the max number of sets.
- */
-typedef __u16 ip_set_id_t;
-
-#define IPSET_INVALID_ID 65535
-
-enum ip_set_dim {
- IPSET_DIM_ZERO = 0,
- IPSET_DIM_ONE,
- IPSET_DIM_TWO,
- IPSET_DIM_THREE,
- /* Max dimension in elements.
- * If changed, new revision of iptables match/target is required.
- */
- IPSET_DIM_MAX = 6,
-};
-
-/* Option flags for kernel operations */
-enum ip_set_kopt {
- IPSET_INV_MATCH = (1 << IPSET_DIM_ZERO),
- IPSET_DIM_ONE_SRC = (1 << IPSET_DIM_ONE),
- IPSET_DIM_TWO_SRC = (1 << IPSET_DIM_TWO),
- IPSET_DIM_THREE_SRC = (1 << IPSET_DIM_THREE),
-};
-
-#endif /* __IP_SET_H */
+++ /dev/null
-#ifndef __IP_SET_BITMAP_H
-#define __IP_SET_BITMAP_H
-
-/* Bitmap type specific error codes */
-enum {
- /* The element is out of the range of the set */
- IPSET_ERR_BITMAP_RANGE = IPSET_ERR_TYPE_SPECIFIC,
- /* The range exceeds the size limit of the set type */
- IPSET_ERR_BITMAP_RANGE_SIZE,
-};
-
-#endif /* __IP_SET_BITMAP_H */
+++ /dev/null
-#ifndef __IP_SET_HASH_H
-#define __IP_SET_HASH_H
-
-/* Hash type specific error codes */
-enum {
- /* Hash is full */
- IPSET_ERR_HASH_FULL = IPSET_ERR_TYPE_SPECIFIC,
- /* Null-valued element */
- IPSET_ERR_HASH_ELEM,
- /* Invalid protocol */
- IPSET_ERR_INVALID_PROTO,
- /* Protocol missing but must be specified */
- IPSET_ERR_MISSING_PROTO,
- /* Range not supported */
- IPSET_ERR_HASH_RANGE_UNSUPPORTED,
- /* Invalid range */
- IPSET_ERR_HASH_RANGE,
-};
-
-#endif /* __IP_SET_HASH_H */
+++ /dev/null
-#ifndef __IP_SET_LIST_H
-#define __IP_SET_LIST_H
-
-/* List type specific error codes */
-enum {
- /* Set name to be added/deleted/tested does not exist. */
- IPSET_ERR_NAME = IPSET_ERR_TYPE_SPECIFIC,
- /* list:set type is not permitted to add */
- IPSET_ERR_LOOP,
- /* Missing reference set */
- IPSET_ERR_BEFORE,
- /* Reference set does not exist */
- IPSET_ERR_NAMEREF,
- /* Set is full */
- IPSET_ERR_LIST_FULL,
- /* Reference set is not added to the set */
- IPSET_ERR_REF_EXIST,
-};
-
-#endif /* __IP_SET_LIST_H */
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#ifndef LIBIPSET_MNL_H
-#define LIBIPSET_MNL_H
-
-#include <stdint.h> /* uintxx_t */
-#include <libmnl/libmnl.h> /* libmnl backend */
-
-#include <libipset/transport.h> /* struct ipset_transport */
-
-#ifndef NFNETLINK_V0
-#define NFNETLINK_V0 0
-
-struct nfgenmsg {
- uint8_t nfgen_family;
- uint8_t version;
- uint16_t res_id;
-};
-#endif
-
-extern int ipset_get_nlmsg_type(const struct nlmsghdr *nlh);
-
-extern const struct ipset_transport ipset_mnl_transport;
-
-#endif /* LIBIPSET_MNL_H */
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#ifndef LIBIPSET_NF_INET_ADDR_H
-#define LIBIPSET_NF_INET_ADDR_H
-
-#include <stdint.h> /* uint32_t */
-#include <netinet/in.h> /* struct in[6]_addr */
-
-/* The structure to hold IP addresses, same as in linux/netfilter.h */
-union nf_inet_addr {
- uint32_t all[4];
- uint32_t ip;
- uint32_t ip6[4];
- struct in_addr in;
- struct in6_addr in6;
-};
-
-#endif /* LIBIPSET_NF_INET_ADDR_H */
+++ /dev/null
-#ifndef LIBIPSET_NFPROTO_H
-#define LIBIPSET_NFPROTO_H
-
-/*
- * The constants to select, same as in linux/netfilter.h.
- * Like nf_inet_addr.h, this is just here so that we need not to rely on
- * the presence of a recent-enough netfilter.h.
- */
-enum {
- NFPROTO_UNSPEC = 0,
- NFPROTO_IPV4 = 2,
- NFPROTO_ARP = 3,
- NFPROTO_BRIDGE = 7,
- NFPROTO_IPV6 = 10,
- NFPROTO_DECNET = 12,
- NFPROTO_NUMPROTO,
-};
-
-#endif /* LIBIPSET_NFPROTO_H */
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#ifndef LIBIPSET_PARSE_H
-#define LIBIPSET_PARSE_H
-
-#include <libipset/data.h> /* enum ipset_opt */
-
-/* For parsing/printing data */
-#define IPSET_CIDR_SEPARATOR "/"
-#define IPSET_RANGE_SEPARATOR "-"
-#define IPSET_ELEM_SEPARATOR ","
-#define IPSET_NAME_SEPARATOR ","
-#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);
-
-extern int ipset_parse_ether(struct ipset_session *session,
- enum ipset_opt opt, const char *str);
-extern int ipset_parse_port(struct ipset_session *session,
- enum ipset_opt opt, const char *str,
- const char *proto);
-extern int ipset_parse_tcpudp_port(struct ipset_session *session,
- enum ipset_opt opt, const char *str,
- const char *proto);
-extern int ipset_parse_tcp_port(struct ipset_session *session,
- enum ipset_opt opt, const char *str);
-extern int ipset_parse_single_tcp_port(struct ipset_session *session,
- enum ipset_opt opt, const char *str);
-extern int ipset_parse_proto(struct ipset_session *session,
- enum ipset_opt opt, const char *str);
-extern int ipset_parse_icmp(struct ipset_session *session,
- enum ipset_opt opt, const char *str);
-extern int ipset_parse_icmpv6(struct ipset_session *session,
- enum ipset_opt opt, const char *str);
-extern int ipset_parse_proto_port(struct ipset_session *session,
- enum ipset_opt opt, const char *str);
-extern int ipset_parse_family(struct ipset_session *session,
- enum ipset_opt opt, const char *str);
-extern int ipset_parse_ip(struct ipset_session *session,
- enum ipset_opt opt, const char *str);
-extern int ipset_parse_single_ip(struct ipset_session *session,
- enum ipset_opt opt, const char *str);
-extern int ipset_parse_net(struct ipset_session *session,
- enum ipset_opt opt, const char *str);
-extern int ipset_parse_range(struct ipset_session *session,
- enum ipset_opt opt, const char *str);
-extern int ipset_parse_netrange(struct ipset_session *session,
- enum ipset_opt opt, const char *str);
-extern int ipset_parse_iprange(struct ipset_session *session,
- enum ipset_opt opt, const char *str);
-extern int ipset_parse_ipnet(struct ipset_session *session,
- enum ipset_opt opt, const char *str);
-extern int ipset_parse_ip4_single6(struct ipset_session *session,
- enum ipset_opt opt, const char *str);
-extern int ipset_parse_ip4_net6(struct ipset_session *session,
- enum ipset_opt opt, const char *str);
-extern int ipset_parse_name(struct ipset_session *session,
- enum ipset_opt opt, const char *str);
-extern int ipset_parse_before(struct ipset_session *session,
- enum ipset_opt opt, const char *str);
-extern int ipset_parse_after(struct ipset_session *session,
- enum ipset_opt opt, const char *str);
-extern int ipset_parse_setname(struct ipset_session *session,
- enum ipset_opt opt, const char *str);
-extern int ipset_parse_uint32(struct ipset_session *session,
- enum ipset_opt opt, const char *str);
-extern int ipset_parse_uint8(struct ipset_session *session,
- enum ipset_opt opt, const char *str);
-extern int ipset_parse_netmask(struct ipset_session *session,
- enum ipset_opt opt, const char *str);
-extern int ipset_parse_flag(struct ipset_session *session,
- enum ipset_opt opt, const char *str);
-extern int ipset_parse_typename(struct ipset_session *session,
- enum ipset_opt opt, const char *str);
-extern int ipset_parse_iface(struct ipset_session *session,
- enum ipset_opt opt, const char *str);
-extern int ipset_parse_output(struct ipset_session *session,
- int opt, const char *str);
-extern int ipset_parse_ignored(struct ipset_session *session,
- enum ipset_opt opt, const char *str);
-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,
- const struct ipset_arg *arg,
- const char *str);
-
-/* Compatibility parser functions */
-extern int ipset_parse_iptimeout(struct ipset_session *session,
- enum ipset_opt opt, const char *str);
-extern int ipset_parse_name_compat(struct ipset_session *session,
- enum ipset_opt opt, const char *str);
-
-#endif /* LIBIPSET_PARSE_H */
+++ /dev/null
-#ifndef _NET_PFXLEN_H
-#define _NET_PFXLEN_H 1
-
-#include <asm/byteorder.h>
-#ifdef HAVE_PFXLEN_H
-#include <linux/netfilter/pfxlen.h>
-#else
-
-#include <libipset/nf_inet_addr.h> /* union nf_inet_addr */
-
-#define E(a, b, c, d) \
- {.ip6 = { \
- __constant_htonl(a), __constant_htonl(b), \
- __constant_htonl(c), __constant_htonl(d), \
- } }
-
-/*
- * This table works for both IPv4 and IPv6;
- * just use prefixlen_netmask_map[prefixlength].ip.
- */
-const union nf_inet_addr prefixlen_netmask_map[] = {
- E(0x00000000, 0x00000000, 0x00000000, 0x00000000),
- E(0x80000000, 0x00000000, 0x00000000, 0x00000000),
- E(0xC0000000, 0x00000000, 0x00000000, 0x00000000),
- E(0xE0000000, 0x00000000, 0x00000000, 0x00000000),
- E(0xF0000000, 0x00000000, 0x00000000, 0x00000000),
- E(0xF8000000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFC000000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFE000000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFF000000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFF800000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFC00000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFE00000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFF00000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFF80000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFC0000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFE0000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFF0000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFF8000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFC000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFE000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFF000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFF800, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFC00, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFE00, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFF00, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFF80, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFFC0, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFFE0, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFFF0, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFFF8, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFC, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFE, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0x80000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xC0000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xE0000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xF0000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xF8000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFC000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFE000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFF000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFF800000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFC00000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFE00000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFF00000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFF80000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFC0000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFE0000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFF0000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFF8000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFC000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFE000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFF000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFF800, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFC00, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFE00, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFF00, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFF80, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFC0, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFE0, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFF0, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFF8, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFC, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFE, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0x80000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xC0000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xE0000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xF0000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xF8000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFC000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFE000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFF800000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFC00000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFE00000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFF00000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFF80000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFC0000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFE0000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF0000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF8000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFC000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF800, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFC00, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFE00, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF00, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF80, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFC0, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFE0, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF0, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF8, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFC, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x80000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xC0000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xE0000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xF0000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xF8000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFC000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFE000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF800000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFC00000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFE00000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFF00000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFF80000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFC0000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFE0000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF0000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF8000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFC000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF800),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFC00),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFE00),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF00),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF80),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFC0),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFE0),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF0),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF8),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFC),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF),
-};
-#endif /* !HAVE_PFXLEN_H */
-
-#define PFXLEN(n) prefixlen_netmask_map[n].ip
-#define PFXLEN6(n) prefixlen_netmask_map[n].ip6
-
-#endif
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#ifndef LIBIPSET_PRINT_H
-#define LIBIPSET_PRINT_H
-
-#include <libipset/data.h> /* enum ipset_opt */
-
-typedef int (*ipset_printfn)(char *buf, unsigned int len,
- const struct ipset_data *data,
- enum ipset_opt opt, uint8_t env);
-
-extern int ipset_print_ether(char *buf, unsigned int len,
- const struct ipset_data *data,
- enum ipset_opt opt, uint8_t env);
-extern int ipset_print_family(char *buf, unsigned int len,
- const struct ipset_data *data,
- enum ipset_opt opt, uint8_t env);
-extern int ipset_print_type(char *buf, unsigned int len,
- const struct ipset_data *data,
- enum ipset_opt opt, uint8_t env);
-extern int ipset_print_ip(char *buf, unsigned int len,
- const struct ipset_data *data,
- enum ipset_opt opt, uint8_t env);
-extern int ipset_print_ipaddr(char *buf, unsigned int len,
- const struct ipset_data *data,
- enum ipset_opt opt, uint8_t env);
-extern int ipset_print_number(char *buf, unsigned int len,
- const struct ipset_data *data,
- enum ipset_opt opt, uint8_t env);
-extern int ipset_print_name(char *buf, unsigned int len,
- const struct ipset_data *data,
- enum ipset_opt opt, uint8_t env);
-extern int ipset_print_port(char *buf, unsigned int len,
- const struct ipset_data *data,
- enum ipset_opt opt, uint8_t env);
-extern int ipset_print_iface(char *buf, unsigned int len,
- const struct ipset_data *data,
- enum ipset_opt opt, uint8_t env);
-extern int ipset_print_proto(char *buf, unsigned int len,
- const struct ipset_data *data,
- enum ipset_opt opt, uint8_t env);
-extern int ipset_print_icmp(char *buf, unsigned int len,
- const struct ipset_data *data,
- enum ipset_opt opt, uint8_t env);
-extern int ipset_print_icmpv6(char *buf, unsigned int len,
- const struct ipset_data *data,
- enum ipset_opt opt, uint8_t env);
-extern int ipset_print_proto_port(char *buf, unsigned int len,
- const struct ipset_data *data,
- enum ipset_opt opt, uint8_t env);
-extern int ipset_print_flag(char *buf, unsigned int len,
- const struct ipset_data *data,
- enum ipset_opt opt, uint8_t env);
-extern int ipset_print_elem(char *buf, unsigned int len,
- const struct ipset_data *data,
- enum ipset_opt opt, uint8_t env);
-
-#define ipset_print_portnum ipset_print_number
-
-extern int ipset_print_data(char *buf, unsigned int len,
- const struct ipset_data *data,
- enum ipset_opt opt, uint8_t env);
-
-#endif /* LIBIPSET_PRINT_H */
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#ifndef LIBIPSET_SESSION_H
-#define LIBIPSET_SESSION_H
-
-#include <stdbool.h> /* bool */
-#include <stdint.h> /* uintxx_t */
-#include <stdio.h> /* printf */
-
-#include <libipset/linux_ip_set.h> /* enum ipset_cmd */
-
-/* Report and output buffer sizes */
-#define IPSET_ERRORBUFLEN 1024
-#define IPSET_OUTBUFLEN 8192
-
-struct ipset_session;
-struct ipset_data;
-struct ipset_handle;
-
-extern struct ipset_data *
- ipset_session_data(const struct ipset_session *session);
-extern struct ipset_handle *
- ipset_session_handle(const struct ipset_session *session);
-extern const struct ipset_type *
- ipset_saved_type(const struct ipset_session *session);
-extern void ipset_session_lineno(struct ipset_session *session,
- uint32_t lineno);
-
-enum ipset_err_type {
- IPSET_ERROR,
- IPSET_WARNING,
-};
-
-extern int ipset_session_report(struct ipset_session *session,
- enum ipset_err_type type,
- const char *fmt, ...);
-
-#define ipset_err(session, fmt, args...) \
- ipset_session_report(session, IPSET_ERROR, fmt , ## args)
-
-#define ipset_warn(session, fmt, args...) \
- ipset_session_report(session, IPSET_WARNING, fmt , ## args)
-
-#define ipset_errptr(session, fmt, args...) ({ \
- ipset_session_report(session, IPSET_ERROR, fmt , ## args); \
- NULL; \
-})
-
-extern void ipset_session_report_reset(struct ipset_session *session);
-extern const char *ipset_session_error(const struct ipset_session *session);
-extern const char *ipset_session_warning(const struct ipset_session *session);
-
-#define ipset_session_data_set(session, opt, value) \
- ipset_data_set(ipset_session_data(session), opt, value)
-#define ipset_session_data_get(session, opt) \
- ipset_data_get(ipset_session_data(session), opt)
-
-/* Environment option flags */
-enum ipset_envopt {
- IPSET_ENV_BIT_SORTED = 0,
- IPSET_ENV_SORTED = (1 << IPSET_ENV_BIT_SORTED),
- IPSET_ENV_BIT_QUIET = 1,
- IPSET_ENV_QUIET = (1 << IPSET_ENV_BIT_QUIET),
- IPSET_ENV_BIT_RESOLVE = 2,
- IPSET_ENV_RESOLVE = (1 << IPSET_ENV_BIT_RESOLVE),
- IPSET_ENV_BIT_EXIST = 3,
- IPSET_ENV_EXIST = (1 << IPSET_ENV_BIT_EXIST),
- IPSET_ENV_BIT_LIST_SETNAME = 4,
- IPSET_ENV_LIST_SETNAME = (1 << IPSET_ENV_BIT_LIST_SETNAME),
- IPSET_ENV_BIT_LIST_HEADER = 5,
- IPSET_ENV_LIST_HEADER = (1 << IPSET_ENV_BIT_LIST_HEADER),
-};
-
-extern int ipset_envopt_parse(struct ipset_session *session,
- int env, const char *str);
-extern bool ipset_envopt_test(struct ipset_session *session,
- enum ipset_envopt env);
-
-enum ipset_output_mode {
- IPSET_LIST_NONE,
- IPSET_LIST_PLAIN,
- IPSET_LIST_SAVE,
- IPSET_LIST_XML,
-};
-
-extern int ipset_session_output(struct ipset_session *session,
- enum ipset_output_mode mode);
-
-extern int ipset_commit(struct ipset_session *session);
-extern int ipset_cmd(struct ipset_session *session, enum ipset_cmd cmd,
- uint32_t lineno);
-
-typedef int (*ipset_outfn)(const char *fmt, ...)
- __attribute__ ((format (printf, 1, 2)));
-
-extern struct ipset_session *ipset_session_init(ipset_outfn outfn);
-extern int ipset_session_fini(struct ipset_session *session);
-
-extern void ipset_debug_msg(const char *dir, void *buffer, int len);
-
-#endif /* LIBIPSET_SESSION_H */
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#ifndef LIBIPSET_TRANSPORT_H
-#define LIBIPSET_TRANSPORT_H
-
-#include <stdint.h> /* uintxx_t */
-#include <linux/netlink.h> /* struct nlmsghdr */
-
-#include <libmnl/libmnl.h> /* mnl_cb_t */
-
-#include <libipset/linux_ip_set.h> /* enum ipset_cmd */
-
-struct ipset_handle;
-
-struct ipset_transport {
- struct ipset_handle * (*init)(mnl_cb_t *cb_ctl, void *data);
- int (*fini)(struct ipset_handle *handle);
- void (*fill_hdr)(struct ipset_handle *handle, enum ipset_cmd cmd,
- void *buffer, size_t len, uint8_t envflags);
- int (*query)(struct ipset_handle *handle, void *buffer, size_t len);
-};
-
-#endif /* LIBIPSET_TRANSPORT_H */
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#ifndef LIBIPSET_TYPES_H
-#define LIBIPSET_TYPES_H
-
-#include <stddef.h> /* NULL */
-#include <stdint.h> /* uintxx_t */
-
-#include <libipset/data.h> /* enum ipset_opt */
-#include <libipset/parse.h> /* ipset_parsefn */
-#include <libipset/print.h> /* ipset_printfn */
-#include <libipset/linux_ip_set.h> /* IPSET_MAXNAMELEN */
-#include <libipset/nfproto.h> /* for NFPROTO_ */
-
-/* Family rules:
- * - NFPROTO_UNSPEC: type is family-neutral
- * - NFPROTO_IPV4: type supports IPv4 only
- * - NFPROTO_IPV6: type supports IPv6 only
- * Special (userspace) ipset-only extra value:
- * - NFPROTO_IPSET_IPV46: type supports both IPv4 and IPv6
- */
-enum {
- NFPROTO_IPSET_IPV46 = 255,
-};
-
-/* The maximal type dimension userspace supports */
-#define IPSET_DIM_UMAX 3
-
-/* Parser options */
-enum {
- IPSET_NO_ARG = -1,
- IPSET_OPTIONAL_ARG,
- IPSET_MANDATORY_ARG,
- IPSET_MANDATORY_ARG2,
-};
-
-struct ipset_session;
-
-/* Parse and print type-specific arguments */
-struct ipset_arg {
- const char *name[2]; /* option names */
- int has_arg; /* mandatory/optional/no arg */
- enum ipset_opt opt; /* argumentum type */
- ipset_parsefn parse; /* parser function */
- ipset_printfn print; /* printing function */
-};
-
-/* Type check against the kernel */
-enum {
- IPSET_KERNEL_MISMATCH = -1,
- IPSET_KERNEL_CHECK_NEEDED,
- IPSET_KERNEL_OK,
-};
-
-/* How element parts are parsed */
-struct ipset_elem {
- ipset_parsefn parse; /* elem parser function */
- ipset_printfn print; /* elem print function */
- enum ipset_opt opt; /* elem option */
-};
-
-/* The set types in userspace
- * we could collapse 'args' and 'mandatory' to two-element lists
- * but for the readability the full list is supported.
- */
-struct ipset_type {
- const char *name;
- uint8_t revision; /* revision number */
- uint8_t family; /* supported family */
- uint8_t dimension; /* elem dimension */
- int8_t kernel_check; /* kernel check */
- bool last_elem_optional; /* last element optional */
- struct ipset_elem elem[IPSET_DIM_UMAX]; /* parse elem */
- ipset_parsefn compat_parse_elem; /* compatibility parser */
- const struct ipset_arg *args[IPSET_CADT_MAX]; /* create/ADT args besides elem */
- uint64_t mandatory[IPSET_CADT_MAX]; /* create/ADT mandatory flags */
- uint64_t full[IPSET_CADT_MAX]; /* full args flags */
- const char *usage; /* terse usage */
- void (*usagefn)(void); /* additional usage */
-
- struct ipset_type *next;
- const char *alias[]; /* name alias(es) */
-};
-
-extern int ipset_cache_add(const char *name, const struct ipset_type *type,
- uint8_t family);
-extern int ipset_cache_del(const char *name);
-extern int ipset_cache_rename(const char *from, const char *to);
-extern int ipset_cache_swap(const char *from, const char *to);
-
-extern int ipset_cache_init(void);
-extern void ipset_cache_fini(void);
-
-extern const struct ipset_type *
- ipset_type_get(struct ipset_session *session, enum ipset_cmd cmd);
-extern const struct ipset_type *
- ipset_type_check(struct ipset_session *session);
-
-extern int ipset_type_add(struct ipset_type *type);
-extern const struct ipset_type *ipset_types(void);
-extern const char *ipset_typename_resolve(const char *str);
-extern bool ipset_match_typename(const char *str,
- const struct ipset_type *t);
-
-#endif /* LIBIPSET_TYPES_H */
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#ifndef LIBIPSET_UI_H
-#define LIBIPSET_UI_H
-
-#include <libipset/linux_ip_set.h> /* enum ipset_cmd */
-
-/* Commands in userspace */
-struct ipset_commands {
- enum ipset_cmd cmd;
- int has_arg;
- const char *name[2];
- const char *help;
-};
-
-extern const struct ipset_commands ipset_commands[];
-
-struct ipset_session;
-struct ipset_data;
-
-/* Environment options */
-struct ipset_envopts {
- int flag;
- int has_arg;
- const char *name[2];
- const char *help;
- int (*parse)(struct ipset_session *s, int flag, const char *str);
- int (*print)(char *buf, unsigned int len,
- const struct ipset_data *data, int flag, uint8_t env);
-};
-
-extern const struct ipset_envopts ipset_envopts[];
-
-extern bool ipset_match_cmd(const char *arg, const char * const name[]);
-extern bool ipset_match_option(const char *arg, const char * const name[]);
-extern bool ipset_match_envopt(const char *arg, const char * const name[]);
-extern void ipset_shift_argv(int *argc, char *argv[], int from);
-extern void ipset_port_usage(void);
-
-#endif /* LIBIPSET_UI_H */
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#ifndef LIBIPSET_UTILS_H
-#define LIBIPSET_UTILS_H
-
-#include <string.h> /* strcmp */
-#include <netinet/in.h> /* struct in[6]_addr */
-
-/* String equality tests */
-#define STREQ(a, b) (strcmp(a, b) == 0)
-#define STRNEQ(a, b, n) (strncmp(a, b, n) == 0)
-#define STRCASEQ(a, b) (strcasecmp(a, b) == 0)
-#define STRNCASEQ(a, b, n) (strncasecmp(a, b, n) == 0)
-
-/* Stringify tokens */
-#define _STR(c) #c
-#define STR(c) _STR(c)
-
-/* Min/max */
-#define MIN(a, b) (a < b ? a : b)
-#define MAX(a, b) (a > b ? a : b)
-
-#define UNUSED __attribute__ ((unused))
-#ifdef NDEBUG
-#define ASSERT_UNUSED UNUSED
-#else
-#define ASSERT_UNUSED
-#endif
-
-#ifndef ARRAY_SIZE
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
-#endif
-
-static inline void
-in4cpy(struct in_addr *dest, const struct in_addr *src)
-{
- dest->s_addr = src->s_addr;
-}
-
-static inline void
-in6cpy(struct in6_addr *dest, const struct in6_addr *src)
-{
- memcpy(dest, src, sizeof(struct in6_addr));
-}
-
-#endif /* LIBIPSET_UTILS_H */
+++ /dev/null
-#ifndef _IP_SET_H
-#define _IP_SET_H
-
-/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
- * Patrick Schaaf <bof@bof.de>
- * Martin Josefsson <gandalf@wlug.westbo.se>
- * Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/types.h>
-#include <linux/netlink.h>
-
-/* The protocol version */
-#define IPSET_PROTOCOL 0x60
-
-/* The max length of strings including NUL: set and type identifiers */
-#define IPSET_MAXNAMELEN 32
-
-/* Message types and commands */
-enum ipset_cmd {
- IPSET_CMD_NONE,
- IPSET_CMD_PROTOCOL, /* 1: Return protocol version */
- IPSET_CMD_CREATE, /* 2: Create a new (empty) set */
- IPSET_CMD_DESTROY, /* 3: Destroy a (empty) set */
- IPSET_CMD_FLUSH, /* 4: Remove all elements from a set */
- IPSET_CMD_RENAME, /* 5: Rename a set */
- IPSET_CMD_SWAP, /* 6: Swap two sets */
- IPSET_CMD_LIST, /* 7: List sets */
- IPSET_CMD_SAVE, /* 8: Save sets */
- IPSET_CMD_ADD, /* 9: Add an element to a set */
- IPSET_CMD_DEL, /* 10: Delete an element from a set */
- IPSET_CMD_TEST, /* 11: Test an element in a set */
- IPSET_CMD_HEADER, /* 12: Get set header data only */
- IPSET_CMD_TYPE, /* 13: Get set type */
- IPSET_MSG_MAX, /* Netlink message commands */
-
- /* Commands in userspace: */
- IPSET_CMD_RESTORE = IPSET_MSG_MAX, /* 14: Enter restore mode */
- IPSET_CMD_HELP, /* 15: Get help */
- IPSET_CMD_VERSION, /* 16: Get program version */
- IPSET_CMD_QUIT, /* 17: Quit from interactive mode */
-
- IPSET_CMD_MAX,
-
- IPSET_CMD_COMMIT = IPSET_CMD_MAX, /* 18: Commit buffered commands */
-};
-
-/* Attributes at command level */
-enum {
- IPSET_ATTR_UNSPEC,
- IPSET_ATTR_PROTOCOL, /* 1: Protocol version */
- IPSET_ATTR_SETNAME, /* 2: Name of the set */
- IPSET_ATTR_TYPENAME, /* 3: Typename */
- IPSET_ATTR_SETNAME2 = IPSET_ATTR_TYPENAME, /* Setname at rename/swap */
- IPSET_ATTR_REVISION, /* 4: Settype revision */
- IPSET_ATTR_FAMILY, /* 5: Settype family */
- IPSET_ATTR_FLAGS, /* 6: Flags at command level */
- IPSET_ATTR_DATA, /* 7: Nested attributes */
- IPSET_ATTR_ADT, /* 8: Multiple data containers */
- IPSET_ATTR_LINENO, /* 9: Restore lineno */
- IPSET_ATTR_PROTOCOL_MIN, /* 10: Minimal supported version number */
- IPSET_ATTR_REVISION_MIN = IPSET_ATTR_PROTOCOL_MIN, /* type rev min */
- __IPSET_ATTR_CMD_MAX,
-};
-#define IPSET_ATTR_CMD_MAX (__IPSET_ATTR_CMD_MAX - 1)
-
-/* CADT specific attributes */
-enum {
- IPSET_ATTR_IP = IPSET_ATTR_UNSPEC + 1,
- IPSET_ATTR_IP_FROM = IPSET_ATTR_IP,
- IPSET_ATTR_IP_TO, /* 2 */
- IPSET_ATTR_CIDR, /* 3 */
- IPSET_ATTR_PORT, /* 4 */
- IPSET_ATTR_PORT_FROM = IPSET_ATTR_PORT,
- IPSET_ATTR_PORT_TO, /* 5 */
- IPSET_ATTR_TIMEOUT, /* 6 */
- IPSET_ATTR_PROTO, /* 7 */
- IPSET_ATTR_CADT_FLAGS, /* 8 */
- IPSET_ATTR_CADT_LINENO = IPSET_ATTR_LINENO, /* 9 */
- /* Reserve empty slots */
- IPSET_ATTR_CADT_MAX = 16,
- /* Create-only specific attributes */
- IPSET_ATTR_GC,
- IPSET_ATTR_HASHSIZE,
- IPSET_ATTR_MAXELEM,
- IPSET_ATTR_NETMASK,
- IPSET_ATTR_PROBES,
- IPSET_ATTR_RESIZE,
- IPSET_ATTR_SIZE,
- /* Kernel-only */
- IPSET_ATTR_ELEMENTS,
- IPSET_ATTR_REFERENCES,
- IPSET_ATTR_MEMSIZE,
-
- __IPSET_ATTR_CREATE_MAX,
-};
-#define IPSET_ATTR_CREATE_MAX (__IPSET_ATTR_CREATE_MAX - 1)
-
-/* ADT specific attributes */
-enum {
- IPSET_ATTR_ETHER = IPSET_ATTR_CADT_MAX + 1,
- IPSET_ATTR_NAME,
- IPSET_ATTR_NAMEREF,
- IPSET_ATTR_IP2,
- IPSET_ATTR_CIDR2,
- IPSET_ATTR_IP2_TO,
- IPSET_ATTR_IFACE,
- __IPSET_ATTR_ADT_MAX,
-};
-#define IPSET_ATTR_ADT_MAX (__IPSET_ATTR_ADT_MAX - 1)
-
-/* IP specific attributes */
-enum {
- IPSET_ATTR_IPADDR_IPV4 = IPSET_ATTR_UNSPEC + 1,
- IPSET_ATTR_IPADDR_IPV6,
- __IPSET_ATTR_IPADDR_MAX,
-};
-#define IPSET_ATTR_IPADDR_MAX (__IPSET_ATTR_IPADDR_MAX - 1)
-
-/* Error codes */
-enum ipset_errno {
- IPSET_ERR_PRIVATE = 4096,
- IPSET_ERR_PROTOCOL,
- IPSET_ERR_FIND_TYPE,
- IPSET_ERR_MAX_SETS,
- IPSET_ERR_BUSY,
- IPSET_ERR_EXIST_SETNAME2,
- IPSET_ERR_TYPE_MISMATCH,
- IPSET_ERR_EXIST,
- IPSET_ERR_INVALID_CIDR,
- IPSET_ERR_INVALID_NETMASK,
- IPSET_ERR_INVALID_FAMILY,
- IPSET_ERR_TIMEOUT,
- IPSET_ERR_REFERENCED,
- IPSET_ERR_IPADDR_IPV4,
- IPSET_ERR_IPADDR_IPV6,
-
- /* Type specific error codes */
- IPSET_ERR_TYPE_SPECIFIC = 4352,
-};
-
-/* Flags at command level */
-enum ipset_cmd_flags {
- IPSET_FLAG_BIT_EXIST = 0,
- IPSET_FLAG_EXIST = (1 << IPSET_FLAG_BIT_EXIST),
- IPSET_FLAG_BIT_LIST_SETNAME = 1,
- IPSET_FLAG_LIST_SETNAME = (1 << IPSET_FLAG_BIT_LIST_SETNAME),
- IPSET_FLAG_BIT_LIST_HEADER = 2,
- IPSET_FLAG_LIST_HEADER = (1 << IPSET_FLAG_BIT_LIST_HEADER),
-};
-
-/* Flags at CADT attribute level */
-enum ipset_cadt_flags {
- IPSET_FLAG_BIT_BEFORE = 0,
- IPSET_FLAG_BEFORE = (1 << IPSET_FLAG_BIT_BEFORE),
- IPSET_FLAG_BIT_PHYSDEV = 1,
- IPSET_FLAG_PHYSDEV = (1 << IPSET_FLAG_BIT_PHYSDEV),
-};
-
-/* Commands with settype-specific attributes */
-enum ipset_adt {
- IPSET_ADD,
- IPSET_DEL,
- IPSET_TEST,
- IPSET_ADT_MAX,
- IPSET_CREATE = IPSET_ADT_MAX,
- IPSET_CADT_MAX,
-};
-
-/* Sets are identified by an index in kernel space. Tweak with ip_set_id_t
- * and IPSET_INVALID_ID if you want to increase the max number of sets.
- */
-typedef __u16 ip_set_id_t;
-
-#define IPSET_INVALID_ID 65535
-
-enum ip_set_dim {
- IPSET_DIM_ZERO = 0,
- IPSET_DIM_ONE,
- IPSET_DIM_TWO,
- IPSET_DIM_THREE,
- /* Max dimension in elements.
- * If changed, new revision of iptables match/target is required.
- */
- IPSET_DIM_MAX = 6,
-};
-
-/* Option flags for kernel operations */
-enum ip_set_kopt {
- IPSET_INV_MATCH = (1 << IPSET_DIM_ZERO),
- IPSET_DIM_ONE_SRC = (1 << IPSET_DIM_ONE),
- IPSET_DIM_TWO_SRC = (1 << IPSET_DIM_TWO),
- IPSET_DIM_THREE_SRC = (1 << IPSET_DIM_THREE),
-};
-
-#ifdef __KERNEL__
-#include <linux/ip.h>
-#include <linux/ipv6.h>
-#include <linux/netlink.h>
-#include <linux/netfilter.h>
-#include <linux/netfilter/x_tables.h>
-#include <linux/vmalloc.h>
-#include <net/netlink.h>
-
-/* Set features */
-enum ip_set_feature {
- IPSET_TYPE_IP_FLAG = 0,
- IPSET_TYPE_IP = (1 << IPSET_TYPE_IP_FLAG),
- IPSET_TYPE_PORT_FLAG = 1,
- IPSET_TYPE_PORT = (1 << IPSET_TYPE_PORT_FLAG),
- IPSET_TYPE_MAC_FLAG = 2,
- IPSET_TYPE_MAC = (1 << IPSET_TYPE_MAC_FLAG),
- IPSET_TYPE_IP2_FLAG = 3,
- IPSET_TYPE_IP2 = (1 << IPSET_TYPE_IP2_FLAG),
- IPSET_TYPE_NAME_FLAG = 4,
- IPSET_TYPE_NAME = (1 << IPSET_TYPE_NAME_FLAG),
- IPSET_TYPE_IFACE_FLAG = 5,
- IPSET_TYPE_IFACE = (1 << IPSET_TYPE_IFACE_FLAG),
- /* Strictly speaking not a feature, but a flag for dumping:
- * this settype must be dumped last */
- IPSET_DUMP_LAST_FLAG = 7,
- IPSET_DUMP_LAST = (1 << IPSET_DUMP_LAST_FLAG),
-};
-
-struct ip_set;
-
-typedef int (*ipset_adtfn)(struct ip_set *set, void *value,
- u32 timeout, u32 flags);
-
-/* Kernel API function options */
-struct ip_set_adt_opt {
- u8 family; /* Actual protocol family */
- u8 dim; /* Dimension of match/target */
- u8 flags; /* Direction and negation flags */
- u32 cmdflags; /* Command-like flags */
- u32 timeout; /* Timeout value */
-};
-
-/* Set type, variant-specific part */
-struct ip_set_type_variant {
- /* Kernelspace: test/add/del entries
- * returns negative error code,
- * zero for no match/success to add/delete
- * positive for matching element */
- int (*kadt)(struct ip_set *set, const struct sk_buff * skb,
- const struct xt_action_param *par,
- enum ipset_adt adt, const struct ip_set_adt_opt *opt);
-
- /* Userspace: test/add/del entries
- * returns negative error code,
- * zero for no match/success to add/delete
- * positive for matching element */
- int (*uadt)(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags, bool retried);
-
- /* Low level add/del/test functions */
- ipset_adtfn adt[IPSET_ADT_MAX];
-
- /* When adding entries and set is full, try to resize the set */
- int (*resize)(struct ip_set *set, bool retried);
- /* Destroy the set */
- void (*destroy)(struct ip_set *set);
- /* Flush the elements */
- void (*flush)(struct ip_set *set);
- /* Expire entries before listing */
- void (*expire)(struct ip_set *set);
- /* List set header data */
- int (*head)(struct ip_set *set, struct sk_buff *skb);
- /* List elements */
- int (*list)(const struct ip_set *set, struct sk_buff *skb,
- struct netlink_callback *cb);
-
- /* Return true if "b" set is the same as "a"
- * according to the create set parameters */
- bool (*same_set)(const struct ip_set *a, const struct ip_set *b);
-};
-
-/* The core set type structure */
-struct ip_set_type {
- struct list_head list;
-
- /* Typename */
- char name[IPSET_MAXNAMELEN];
- /* Protocol version */
- u8 protocol;
- /* Set features to control swapping */
- u8 features;
- /* Set type dimension */
- u8 dimension;
- /*
- * Supported family: may be NFPROTO_UNSPEC for both
- * NFPROTO_IPV4/NFPROTO_IPV6.
- */
- u8 family;
- /* Type revisions */
- u8 revision_min, revision_max;
-
- /* Create set */
- 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;
-};
-
-/* register and unregister set type */
-extern int ip_set_type_register(struct ip_set_type *set_type);
-extern void ip_set_type_unregister(struct ip_set_type *set_type);
-
-/* A generic IP set */
-struct ip_set {
- /* The name of the set */
- char name[IPSET_MAXNAMELEN];
- /* Lock protecting the set data */
- rwlock_t lock;
- /* References to the set */
- u32 ref;
- /* The core set type */
- struct ip_set_type *type;
- /* The type variant doing the real job */
- const struct ip_set_type_variant *variant;
- /* The actual INET family of the set */
- u8 family;
- /* The type revision */
- u8 revision;
- /* The type specific data */
- void *data;
-};
-
-/* register and unregister set references */
-extern ip_set_id_t ip_set_get_byname(const char *name, struct ip_set **set);
-extern void ip_set_put_byindex(ip_set_id_t index);
-extern const char *ip_set_name_byindex(ip_set_id_t index);
-extern ip_set_id_t ip_set_nfnl_get(const char *name);
-extern ip_set_id_t ip_set_nfnl_get_byindex(ip_set_id_t index);
-extern void ip_set_nfnl_put(ip_set_id_t index);
-
-/* API for iptables set match, and SET target */
-
-extern int ip_set_add(ip_set_id_t id, const struct sk_buff *skb,
- const struct xt_action_param *par,
- const struct ip_set_adt_opt *opt);
-extern int ip_set_del(ip_set_id_t id, const struct sk_buff *skb,
- const struct xt_action_param *par,
- const struct ip_set_adt_opt *opt);
-extern int ip_set_test(ip_set_id_t id, const struct sk_buff *skb,
- const struct xt_action_param *par,
- const struct ip_set_adt_opt *opt);
-
-/* Utility functions */
-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);
-
-static inline int
-ip_set_get_hostipaddr4(struct nlattr *nla, u32 *ipaddr)
-{
- __be32 ip;
- int ret = ip_set_get_ipaddr4(nla, &ip);
-
- if (ret)
- return ret;
- *ipaddr = ntohl(ip);
- return 0;
-}
-
-/* Ignore IPSET_ERR_EXIST errors if asked to do so? */
-static inline bool
-ip_set_eexist(int ret, u32 flags)
-{
- return ret == -IPSET_ERR_EXIST && (flags & IPSET_FLAG_EXIST);
-}
-
-/* Check the NLA_F_NET_BYTEORDER flag */
-static inline bool
-ip_set_attr_netorder(struct nlattr *tb[], int type)
-{
- return tb[type] && (tb[type]->nla_type & NLA_F_NET_BYTEORDER);
-}
-
-static inline bool
-ip_set_optattr_netorder(struct nlattr *tb[], int type)
-{
- return !tb[type] || (tb[type]->nla_type & NLA_F_NET_BYTEORDER);
-}
-
-/* Useful converters */
-static inline u32
-ip_set_get_h32(const struct nlattr *attr)
-{
- return ntohl(nla_get_be32(attr));
-}
-
-static inline u16
-ip_set_get_h16(const struct nlattr *attr)
-{
- return ntohs(nla_get_be16(attr));
-}
-
-#define ipset_nest_start(skb, attr) nla_nest_start(skb, attr | NLA_F_NESTED)
-#define ipset_nest_end(skb, start) nla_nest_end(skb, start)
-
-#ifndef NLA_PUT_NET16
-#define NLA_PUT_NET16(skb, attrtype, value) \
- NLA_PUT_BE16(skb, attrtype | NLA_F_NET_BYTEORDER, value)
-#endif
-#ifndef NLA_PUT_NET32
-#define NLA_PUT_NET32(skb, attrtype, value) \
- NLA_PUT_BE32(skb, attrtype | NLA_F_NET_BYTEORDER, value)
-#endif
-#ifndef NLA_PUT_NET64
-#define NLA_PUT_NET64(skb, attrtype, value) \
- NLA_PUT_BE64(skb, attrtype | NLA_F_NET_BYTEORDER, value)
-#endif
-
-#define NLA_PUT_IPADDR4(skb, type, ipaddr) \
-do { \
- struct nlattr *__nested = ipset_nest_start(skb, type); \
- \
- if (!__nested) \
- goto nla_put_failure; \
- NLA_PUT_NET32(skb, IPSET_ATTR_IPADDR_IPV4, ipaddr); \
- ipset_nest_end(skb, __nested); \
-} while (0)
-
-#define NLA_PUT_IPADDR6(skb, type, ipaddrptr) \
-do { \
- struct nlattr *__nested = ipset_nest_start(skb, type); \
- \
- if (!__nested) \
- goto nla_put_failure; \
- NLA_PUT(skb, IPSET_ATTR_IPADDR_IPV6, \
- sizeof(struct in6_addr), ipaddrptr); \
- ipset_nest_end(skb, __nested); \
-} while (0)
-
-/* Get address from skbuff */
-static inline __be32
-ip4addr(const struct sk_buff *skb, bool src)
-{
- return src ? ip_hdr(skb)->saddr : ip_hdr(skb)->daddr;
-}
-
-static inline void
-ip4addrptr(const struct sk_buff *skb, bool src, __be32 *addr)
-{
- *addr = src ? ip_hdr(skb)->saddr : ip_hdr(skb)->daddr;
-}
-
-static inline void
-ip6addrptr(const struct sk_buff *skb, bool src, struct in6_addr *addr)
-{
- memcpy(addr, src ? &ipv6_hdr(skb)->saddr : &ipv6_hdr(skb)->daddr,
- sizeof(*addr));
-}
-
-/* Calculate the bytes required to store the inclusive range of a-b */
-static inline int
-bitmap_bytes(u32 a, u32 b)
-{
- return 4 * ((((b - a + 8) / 8) + 3) / 4);
-}
-
-#endif /* __KERNEL__ */
-
-/* Interface to iptables/ip6tables */
-
-#define SO_IP_SET 83
-
-union ip_set_name_index {
- char name[IPSET_MAXNAMELEN];
- ip_set_id_t index;
-};
-
-#define IP_SET_OP_GET_BYNAME 0x00000006 /* Get set index by name */
-struct ip_set_req_get_set {
- unsigned op;
- unsigned version;
- union ip_set_name_index set;
-};
-
-#define IP_SET_OP_GET_BYINDEX 0x00000007 /* Get set name by index */
-/* Uses ip_set_req_get_set */
-
-#define IP_SET_OP_VERSION 0x00000100 /* Ask kernel version */
-struct ip_set_req_version {
- unsigned op;
- unsigned version;
-};
-
-#endif /*_IP_SET_H */
+++ /dev/null
-#ifndef _IP_SET_AHASH_H
-#define _IP_SET_AHASH_H
-
-#include <linux/rcupdate.h>
-#include "jhash.h"
-#include "ip_set_timeout.h"
-
-#define CONCAT(a, b, c) a##b##c
-#define TOKEN(a, b, c) CONCAT(a, b, c)
-
-#define type_pf_next TOKEN(TYPE, PF, _elem)
-
-/* Hashing which uses arrays to resolve clashing. The hash table is resized
- * (doubled) when searching becomes too long.
- * Internally jhash is used with the assumption that the size of the
- * stored data is a multiple of sizeof(u32). If storage supports timeout,
- * the timeout field must be the last one in the data structure - that field
- * is ignored when computing the hash key.
- *
- * Readers and resizing
- *
- * Resizing can be triggered by userspace command only, and those
- * are serialized by the nfnl mutex. During resizing the set is
- * read-locked, so the only possible concurrent operations are
- * the kernel side readers. Those must be protected by proper RCU locking.
- */
-
-/* Number of elements to store in an initial array block */
-#define AHASH_INIT_SIZE 4
-/* Max number of elements to store in an array block */
-#define AHASH_MAX_SIZE (3*AHASH_INIT_SIZE)
-
-/* Max number of elements can be tuned */
-#ifdef IP_SET_HASH_WITH_MULTI
-#define AHASH_MAX(h) ((h)->ahash_max)
-
-static inline u8
-tune_ahash_max(u8 curr, u32 multi)
-{
- u32 n;
-
- if (multi < curr)
- return curr;
-
- n = curr + AHASH_INIT_SIZE;
- /* Currently, at listing one hash bucket must fit into a message.
- * Therefore we have a hard limit here.
- */
- return n > curr && n <= 64 ? n : curr;
-}
-#define TUNE_AHASH_MAX(h, multi) \
- ((h)->ahash_max = tune_ahash_max((h)->ahash_max, multi))
-#else
-#define AHASH_MAX(h) AHASH_MAX_SIZE
-#define TUNE_AHASH_MAX(h, multi)
-#endif
-
-/* A hash bucket */
-struct hbucket {
- void *value; /* the array of the values */
- u8 size; /* size of the array */
- u8 pos; /* position of the first free entry */
-};
-
-/* The hash table: the table size stored here in order to make resizing easy */
-struct htable {
- u8 htable_bits; /* size of hash table == 2^htable_bits */
- struct hbucket bucket[0]; /* hashtable buckets */
-};
-
-#define hbucket(h, i) (&((h)->bucket[i]))
-
-/* Book-keeping of the prefixes added to the set */
-struct ip_set_hash_nets {
- u8 cidr; /* the different cidr values in the set */
- u32 nets; /* number of elements per cidr */
-};
-
-/* The generic ip_set hash structure */
-struct ip_set_hash {
- struct htable *table; /* the hash table */
- u32 maxelem; /* max elements in the hash */
- u32 elements; /* current element (vs timeout) */
- u32 initval; /* random jhash init value */
- u32 timeout; /* timeout value, if enabled */
- struct timer_list gc; /* garbage collection when timeout enabled */
- struct type_pf_next next; /* temporary storage for uadd */
-#ifdef IP_SET_HASH_WITH_MULTI
- u8 ahash_max; /* max elements in an array block */
-#endif
-#ifdef IP_SET_HASH_WITH_NETMASK
- u8 netmask; /* netmask value for subnets to store */
-#endif
-#ifdef IP_SET_HASH_WITH_RBTREE
- struct rb_root rbtree;
-#endif
-#ifdef IP_SET_HASH_WITH_NETS
- struct ip_set_hash_nets nets[0]; /* book-keeping of prefixes */
-#endif
-};
-
-/* Compute htable_bits from the user input parameter hashsize */
-static u8
-htable_bits(u32 hashsize)
-{
- /* Assume that hashsize == 2^htable_bits */
- u8 bits = fls(hashsize - 1);
- if (jhash_size(bits) != hashsize)
- /* Round up to the first 2^n value */
- bits = fls(hashsize);
-
- return bits;
-}
-
-#ifdef IP_SET_HASH_WITH_NETS
-
-#define SET_HOST_MASK(family) (family == AF_INET ? 32 : 128)
-
-/* Network cidr size book keeping when the hash stores different
- * sized networks */
-static void
-add_cidr(struct ip_set_hash *h, u8 cidr, u8 host_mask)
-{
- u8 i;
-
- ++h->nets[cidr-1].nets;
-
- pr_debug("add_cidr added %u: %u\n", cidr, h->nets[cidr-1].nets);
-
- if (h->nets[cidr-1].nets > 1)
- return;
-
- /* New cidr size */
- for (i = 0; i < host_mask && h->nets[i].cidr; i++) {
- /* Add in increasing prefix order, so larger cidr first */
- if (h->nets[i].cidr < cidr)
- swap(h->nets[i].cidr, cidr);
- }
- if (i < host_mask)
- h->nets[i].cidr = cidr;
-}
-
-static void
-del_cidr(struct ip_set_hash *h, u8 cidr, u8 host_mask)
-{
- u8 i;
-
- --h->nets[cidr-1].nets;
-
- pr_debug("del_cidr deleted %u: %u\n", cidr, h->nets[cidr-1].nets);
-
- if (h->nets[cidr-1].nets != 0)
- return;
-
- /* All entries with this cidr size deleted, so cleanup h->cidr[] */
- for (i = 0; i < host_mask - 1 && h->nets[i].cidr; i++) {
- if (h->nets[i].cidr == cidr)
- h->nets[i].cidr = cidr = h->nets[i+1].cidr;
- }
- h->nets[i - 1].cidr = 0;
-}
-#endif
-
-/* Destroy the hashtable part of the set */
-static void
-ahash_destroy(struct htable *t)
-{
- struct hbucket *n;
- u32 i;
-
- for (i = 0; i < jhash_size(t->htable_bits); i++) {
- n = hbucket(t, i);
- if (n->size)
- /* FIXME: use slab cache */
- kfree(n->value);
- }
-
- ip_set_free(t);
-}
-
-/* Calculate the actual memory size of the set data */
-static size_t
-ahash_memsize(const struct ip_set_hash *h, size_t dsize, u8 host_mask)
-{
- u32 i;
- struct htable *t = h->table;
- size_t memsize = sizeof(*h)
- + sizeof(*t)
-#ifdef IP_SET_HASH_WITH_NETS
- + sizeof(struct ip_set_hash_nets) * host_mask
-#endif
- + jhash_size(t->htable_bits) * sizeof(struct hbucket);
-
- for (i = 0; i < jhash_size(t->htable_bits); i++)
- memsize += t->bucket[i].size * dsize;
-
- return memsize;
-}
-
-/* Flush a hash type of set: destroy all elements */
-static void
-ip_set_hash_flush(struct ip_set *set)
-{
- struct ip_set_hash *h = set->data;
- struct htable *t = h->table;
- struct hbucket *n;
- u32 i;
-
- for (i = 0; i < jhash_size(t->htable_bits); i++) {
- n = hbucket(t, i);
- if (n->size) {
- n->size = n->pos = 0;
- /* FIXME: use slab cache */
- kfree(n->value);
- }
- }
-#ifdef IP_SET_HASH_WITH_NETS
- memset(h->nets, 0, sizeof(struct ip_set_hash_nets)
- * SET_HOST_MASK(set->family));
-#endif
- h->elements = 0;
-}
-
-/* Destroy a hash type of set */
-static void
-ip_set_hash_destroy(struct ip_set *set)
-{
- struct ip_set_hash *h = set->data;
-
- if (with_timeout(h->timeout))
- del_timer_sync(&h->gc);
-
- ahash_destroy(h->table);
-#ifdef IP_SET_HASH_WITH_RBTREE
- rbtree_destroy(&h->rbtree);
-#endif
- kfree(h);
-
- set->data = NULL;
-}
-
-#endif /* _IP_SET_AHASH_H */
-
-#ifndef HKEY_DATALEN
-#define HKEY_DATALEN sizeof(struct type_pf_elem)
-#endif
-
-#define HKEY(data, initval, htable_bits) \
-(jhash2((u32 *)(data), HKEY_DATALEN/sizeof(u32), initval) \
- & jhash_mask(htable_bits))
-
-#define CONCAT(a, b, c) a##b##c
-#define TOKEN(a, b, c) CONCAT(a, b, c)
-
-/* Type/family dependent function prototypes */
-
-#define type_pf_data_equal TOKEN(TYPE, PF, _data_equal)
-#define type_pf_data_isnull TOKEN(TYPE, PF, _data_isnull)
-#define type_pf_data_copy TOKEN(TYPE, PF, _data_copy)
-#define type_pf_data_zero_out TOKEN(TYPE, PF, _data_zero_out)
-#define type_pf_data_netmask TOKEN(TYPE, PF, _data_netmask)
-#define type_pf_data_list TOKEN(TYPE, PF, _data_list)
-#define type_pf_data_tlist TOKEN(TYPE, PF, _data_tlist)
-#define type_pf_data_next TOKEN(TYPE, PF, _data_next)
-
-#define type_pf_elem TOKEN(TYPE, PF, _elem)
-#define type_pf_telem TOKEN(TYPE, PF, _telem)
-#define type_pf_data_timeout TOKEN(TYPE, PF, _data_timeout)
-#define type_pf_data_expired TOKEN(TYPE, PF, _data_expired)
-#define type_pf_data_timeout_set TOKEN(TYPE, PF, _data_timeout_set)
-
-#define type_pf_elem_add TOKEN(TYPE, PF, _elem_add)
-#define type_pf_add TOKEN(TYPE, PF, _add)
-#define type_pf_del TOKEN(TYPE, PF, _del)
-#define type_pf_test_cidrs TOKEN(TYPE, PF, _test_cidrs)
-#define type_pf_test TOKEN(TYPE, PF, _test)
-
-#define type_pf_elem_tadd TOKEN(TYPE, PF, _elem_tadd)
-#define type_pf_del_telem TOKEN(TYPE, PF, _ahash_del_telem)
-#define type_pf_expire TOKEN(TYPE, PF, _expire)
-#define type_pf_tadd TOKEN(TYPE, PF, _tadd)
-#define type_pf_tdel TOKEN(TYPE, PF, _tdel)
-#define type_pf_ttest_cidrs TOKEN(TYPE, PF, _ahash_ttest_cidrs)
-#define type_pf_ttest TOKEN(TYPE, PF, _ahash_ttest)
-
-#define type_pf_resize TOKEN(TYPE, PF, _resize)
-#define type_pf_tresize TOKEN(TYPE, PF, _tresize)
-#define type_pf_flush ip_set_hash_flush
-#define type_pf_destroy ip_set_hash_destroy
-#define type_pf_head TOKEN(TYPE, PF, _head)
-#define type_pf_list TOKEN(TYPE, PF, _list)
-#define type_pf_tlist TOKEN(TYPE, PF, _tlist)
-#define type_pf_same_set TOKEN(TYPE, PF, _same_set)
-#define type_pf_kadt TOKEN(TYPE, PF, _kadt)
-#define type_pf_uadt TOKEN(TYPE, PF, _uadt)
-#define type_pf_gc TOKEN(TYPE, PF, _gc)
-#define type_pf_gc_init TOKEN(TYPE, PF, _gc_init)
-#define type_pf_variant TOKEN(TYPE, PF, _variant)
-#define type_pf_tvariant TOKEN(TYPE, PF, _tvariant)
-
-/* Flavour without timeout */
-
-/* Get the ith element from the array block n */
-#define ahash_data(n, i) \
- ((struct type_pf_elem *)((n)->value) + (i))
-
-/* Add an element to the hash table when resizing the set:
- * we spare the maintenance of the internal counters. */
-static int
-type_pf_elem_add(struct hbucket *n, const struct type_pf_elem *value,
- u8 ahash_max)
-{
- if (n->pos >= n->size) {
- void *tmp;
-
- if (n->size >= ahash_max)
- /* Trigger rehashing */
- return -EAGAIN;
-
- tmp = kzalloc((n->size + AHASH_INIT_SIZE)
- * sizeof(struct type_pf_elem),
- GFP_ATOMIC);
- if (!tmp)
- return -ENOMEM;
- if (n->size) {
- memcpy(tmp, n->value,
- sizeof(struct type_pf_elem) * n->size);
- kfree(n->value);
- }
- n->value = tmp;
- n->size += AHASH_INIT_SIZE;
- }
- type_pf_data_copy(ahash_data(n, n->pos++), value);
- return 0;
-}
-
-/* Resize a hash: create a new hash table with doubling the hashsize
- * and inserting the elements to it. Repeat until we succeed or
- * fail due to memory pressures. */
-static int
-type_pf_resize(struct ip_set *set, bool retried)
-{
- struct ip_set_hash *h = set->data;
- struct htable *t, *orig = h->table;
- u8 htable_bits = orig->htable_bits;
- const struct type_pf_elem *data;
- struct hbucket *n, *m;
- u32 i, j;
- int ret;
-
-retry:
- ret = 0;
- htable_bits++;
- pr_debug("attempt to resize set %s from %u to %u, t %p\n",
- set->name, orig->htable_bits, htable_bits, orig);
- if (!htable_bits)
- /* 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));
- if (!t)
- return -ENOMEM;
- t->htable_bits = htable_bits;
-
- read_lock_bh(&set->lock);
- for (i = 0; i < jhash_size(orig->htable_bits); i++) {
- n = hbucket(orig, i);
- for (j = 0; j < n->pos; j++) {
- data = ahash_data(n, j);
- m = hbucket(t, HKEY(data, h->initval, htable_bits));
- ret = type_pf_elem_add(m, data, AHASH_MAX(h));
- if (ret < 0) {
- read_unlock_bh(&set->lock);
- ahash_destroy(t);
- if (ret == -EAGAIN)
- goto retry;
- return ret;
- }
- }
- }
-
- rcu_assign_pointer(h->table, t);
- read_unlock_bh(&set->lock);
-
- /* Give time to other readers of the set */
- synchronize_rcu_bh();
-
- pr_debug("set %s resized from %u (%p) to %u (%p)\n", set->name,
- orig->htable_bits, orig, t->htable_bits, t);
- ahash_destroy(orig);
-
- return 0;
-}
-
-static inline void
-type_pf_data_next(struct ip_set_hash *h, const struct type_pf_elem *d);
-
-/* 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, u32 flags)
-{
- struct ip_set_hash *h = set->data;
- struct htable *t;
- const struct type_pf_elem *d = value;
- struct hbucket *n;
- int i, ret = 0;
- u32 key, multi = 0;
-
- if (h->elements >= h->maxelem)
- return -IPSET_ERR_HASH_FULL;
-
- rcu_read_lock_bh();
- t = rcu_dereference_bh(h->table);
- key = HKEY(value, h->initval, t->htable_bits);
- n = hbucket(t, key);
- for (i = 0; i < n->pos; i++)
- if (type_pf_data_equal(ahash_data(n, i), d, &multi)) {
- ret = -IPSET_ERR_EXIST;
- goto out;
- }
- TUNE_AHASH_MAX(h, multi);
- ret = type_pf_elem_add(n, value, AHASH_MAX(h));
- if (ret != 0) {
- if (ret == -EAGAIN)
- type_pf_data_next(h, d);
- goto out;
- }
-
-#ifdef IP_SET_HASH_WITH_NETS
- add_cidr(h, d->cidr, HOST_MASK);
-#endif
- h->elements++;
-out:
- rcu_read_unlock_bh();
- return ret;
-}
-
-/* Delete an element from the hash: swap it with the last element
- * and free up space if possible.
- */
-static int
-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;
- const struct type_pf_elem *d = value;
- struct hbucket *n;
- int i;
- struct type_pf_elem *data;
- u32 key, multi = 0;
-
- key = HKEY(value, h->initval, t->htable_bits);
- n = hbucket(t, key);
- for (i = 0; i < n->pos; i++) {
- data = ahash_data(n, i);
- if (!type_pf_data_equal(data, d, &multi))
- continue;
- if (i != n->pos - 1)
- /* Not last one */
- type_pf_data_copy(data, ahash_data(n, n->pos - 1));
-
- n->pos--;
- h->elements--;
-#ifdef IP_SET_HASH_WITH_NETS
- del_cidr(h, d->cidr, HOST_MASK);
-#endif
- if (n->pos + AHASH_INIT_SIZE < n->size) {
- void *tmp = kzalloc((n->size - AHASH_INIT_SIZE)
- * sizeof(struct type_pf_elem),
- GFP_ATOMIC);
- if (!tmp)
- return 0;
- n->size -= AHASH_INIT_SIZE;
- memcpy(tmp, n->value,
- n->size * sizeof(struct type_pf_elem));
- kfree(n->value);
- n->value = tmp;
- }
- return 0;
- }
-
- return -IPSET_ERR_EXIST;
-}
-
-#ifdef IP_SET_HASH_WITH_NETS
-
-/* Special test function which takes into account the different network
- * sizes added to the set */
-static int
-type_pf_test_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout)
-{
- struct ip_set_hash *h = set->data;
- struct htable *t = h->table;
- struct hbucket *n;
- const struct type_pf_elem *data;
- int i, j = 0;
- u32 key, multi = 0;
- u8 host_mask = SET_HOST_MASK(set->family);
-
- pr_debug("test by nets\n");
- for (; j < host_mask && h->nets[j].cidr && !multi; j++) {
- type_pf_data_netmask(d, h->nets[j].cidr);
- key = HKEY(d, h->initval, t->htable_bits);
- n = hbucket(t, key);
- for (i = 0; i < n->pos; i++) {
- data = ahash_data(n, i);
- if (type_pf_data_equal(data, d, &multi))
- return 1;
- }
- }
- return 0;
-}
-#endif
-
-/* Test whether the element is added to the set */
-static int
-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;
- struct type_pf_elem *d = value;
- struct hbucket *n;
- const struct type_pf_elem *data;
- int i;
- u32 key, multi = 0;
-
-#ifdef IP_SET_HASH_WITH_NETS
- /* If we test an IP address and not a network address,
- * try all possible network sizes */
- if (d->cidr == SET_HOST_MASK(set->family))
- return type_pf_test_cidrs(set, d, timeout);
-#endif
-
- key = HKEY(d, h->initval, t->htable_bits);
- n = hbucket(t, key);
- for (i = 0; i < n->pos; i++) {
- data = ahash_data(n, i);
- if (type_pf_data_equal(data, d, &multi))
- return 1;
- }
- return 0;
-}
-
-/* Reply a HEADER request: fill out the header part of the set */
-static int
-type_pf_head(struct ip_set *set, struct sk_buff *skb)
-{
- const struct ip_set_hash *h = set->data;
- struct nlattr *nested;
- size_t memsize;
-
- read_lock_bh(&set->lock);
- memsize = ahash_memsize(h, with_timeout(h->timeout)
- ? sizeof(struct type_pf_telem)
- : sizeof(struct type_pf_elem),
- set->family == AF_INET ? 32 : 128);
- read_unlock_bh(&set->lock);
-
- nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
- if (!nested)
- goto nla_put_failure;
- NLA_PUT_NET32(skb, IPSET_ATTR_HASHSIZE,
- htonl(jhash_size(h->table->htable_bits)));
- NLA_PUT_NET32(skb, IPSET_ATTR_MAXELEM, htonl(h->maxelem));
-#ifdef IP_SET_HASH_WITH_NETMASK
- if (h->netmask != HOST_MASK)
- NLA_PUT_U8(skb, IPSET_ATTR_NETMASK, h->netmask);
-#endif
- 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));
- ipset_nest_end(skb, nested);
-
- return 0;
-nla_put_failure:
- return -EMSGSIZE;
-}
-
-/* Reply a LIST/SAVE request: dump the elements of the specified set */
-static int
-type_pf_list(const struct ip_set *set,
- struct sk_buff *skb, struct netlink_callback *cb)
-{
- const struct ip_set_hash *h = set->data;
- const struct htable *t = h->table;
- struct nlattr *atd, *nested;
- const struct hbucket *n;
- const struct type_pf_elem *data;
- u32 first = cb->args[2];
- /* We assume that one hash bucket fills into one page */
- void *incomplete;
- int i;
-
- atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
- if (!atd)
- 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);
- n = hbucket(t, cb->args[2]);
- pr_debug("cb->args[2]: %lu, t %p n %p\n", cb->args[2], t, n);
- for (i = 0; i < n->pos; i++) {
- data = ahash_data(n, i);
- pr_debug("list hash %lu hbucket %p i %u, data %p\n",
- cb->args[2], n, i, data);
- nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
- if (!nested) {
- if (cb->args[2] == first) {
- nla_nest_cancel(skb, atd);
- return -EMSGSIZE;
- } else
- goto nla_put_failure;
- }
- if (type_pf_data_list(skb, data))
- goto nla_put_failure;
- ipset_nest_end(skb, nested);
- }
- }
- ipset_nest_end(skb, atd);
- /* Set listing finished */
- cb->args[2] = 0;
-
- return 0;
-
-nla_put_failure:
- nlmsg_trim(skb, incomplete);
- ipset_nest_end(skb, atd);
- if (unlikely(first == cb->args[2])) {
- 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;
-}
-
-static int
-type_pf_kadt(struct ip_set *set, const struct sk_buff * skb,
- const struct xt_action_param *par,
- enum ipset_adt adt, const struct ip_set_adt_opt *opt);
-static int
-type_pf_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags, bool retried);
-
-static const struct ip_set_type_variant type_pf_variant = {
- .kadt = type_pf_kadt,
- .uadt = type_pf_uadt,
- .adt = {
- [IPSET_ADD] = type_pf_add,
- [IPSET_DEL] = type_pf_del,
- [IPSET_TEST] = type_pf_test,
- },
- .destroy = type_pf_destroy,
- .flush = type_pf_flush,
- .head = type_pf_head,
- .list = type_pf_list,
- .resize = type_pf_resize,
- .same_set = type_pf_same_set,
-};
-
-/* Flavour with timeout support */
-
-#define ahash_tdata(n, i) \
- (struct type_pf_elem *)((struct type_pf_telem *)((n)->value) + (i))
-
-static inline u32
-type_pf_data_timeout(const struct type_pf_elem *data)
-{
- const struct type_pf_telem *tdata =
- (const struct type_pf_telem *) data;
-
- return tdata->timeout;
-}
-
-static inline bool
-type_pf_data_expired(const struct type_pf_elem *data)
-{
- const struct type_pf_telem *tdata =
- (const struct type_pf_telem *) data;
-
- return ip_set_timeout_expired(tdata->timeout);
-}
-
-static inline void
-type_pf_data_timeout_set(struct type_pf_elem *data, u32 timeout)
-{
- struct type_pf_telem *tdata = (struct type_pf_telem *) data;
-
- tdata->timeout = ip_set_timeout_set(timeout);
-}
-
-static int
-type_pf_elem_tadd(struct hbucket *n, const struct type_pf_elem *value,
- u8 ahash_max, u32 timeout)
-{
- struct type_pf_elem *data;
-
- if (n->pos >= n->size) {
- void *tmp;
-
- if (n->size >= ahash_max)
- /* Trigger rehashing */
- return -EAGAIN;
-
- tmp = kzalloc((n->size + AHASH_INIT_SIZE)
- * sizeof(struct type_pf_telem),
- GFP_ATOMIC);
- if (!tmp)
- return -ENOMEM;
- if (n->size) {
- memcpy(tmp, n->value,
- sizeof(struct type_pf_telem) * n->size);
- kfree(n->value);
- }
- n->value = tmp;
- n->size += AHASH_INIT_SIZE;
- }
- data = ahash_tdata(n, n->pos++);
- type_pf_data_copy(data, value);
- type_pf_data_timeout_set(data, timeout);
- return 0;
-}
-
-/* Delete expired elements from the hashtable */
-static void
-type_pf_expire(struct ip_set_hash *h)
-{
- struct htable *t = h->table;
- struct hbucket *n;
- struct type_pf_elem *data;
- u32 i;
- int j;
-
- for (i = 0; i < jhash_size(t->htable_bits); i++) {
- n = hbucket(t, i);
- for (j = 0; j < n->pos; j++) {
- data = ahash_tdata(n, j);
- if (type_pf_data_expired(data)) {
- pr_debug("expired %u/%u\n", i, j);
-#ifdef IP_SET_HASH_WITH_NETS
- del_cidr(h, data->cidr, HOST_MASK);
-#endif
- if (j != n->pos - 1)
- /* Not last one */
- type_pf_data_copy(data,
- ahash_tdata(n, n->pos - 1));
- n->pos--;
- h->elements--;
- }
- }
- if (n->pos + AHASH_INIT_SIZE < n->size) {
- void *tmp = kzalloc((n->size - AHASH_INIT_SIZE)
- * sizeof(struct type_pf_telem),
- GFP_ATOMIC);
- if (!tmp)
- /* Still try to delete expired elements */
- continue;
- n->size -= AHASH_INIT_SIZE;
- memcpy(tmp, n->value,
- n->size * sizeof(struct type_pf_telem));
- kfree(n->value);
- n->value = tmp;
- }
- }
-}
-
-static int
-type_pf_tresize(struct ip_set *set, bool retried)
-{
- struct ip_set_hash *h = set->data;
- struct htable *t, *orig = h->table;
- u8 htable_bits = orig->htable_bits;
- const struct type_pf_elem *data;
- struct hbucket *n, *m;
- u32 i, j;
- int ret;
-
- /* Try to cleanup once */
- if (!retried) {
- i = h->elements;
- write_lock_bh(&set->lock);
- type_pf_expire(set->data);
- write_unlock_bh(&set->lock);
- if (h->elements < i)
- return 0;
- }
-
-retry:
- ret = 0;
- htable_bits++;
- if (!htable_bits)
- /* 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));
- if (!t)
- return -ENOMEM;
- t->htable_bits = htable_bits;
-
- read_lock_bh(&set->lock);
- for (i = 0; i < jhash_size(orig->htable_bits); i++) {
- n = hbucket(orig, i);
- for (j = 0; j < n->pos; j++) {
- data = ahash_tdata(n, j);
- m = hbucket(t, HKEY(data, h->initval, htable_bits));
- ret = type_pf_elem_tadd(m, data, AHASH_MAX(h),
- type_pf_data_timeout(data));
- if (ret < 0) {
- read_unlock_bh(&set->lock);
- ahash_destroy(t);
- if (ret == -EAGAIN)
- goto retry;
- return ret;
- }
- }
- }
-
- rcu_assign_pointer(h->table, t);
- read_unlock_bh(&set->lock);
-
- /* Give time to other readers of the set */
- synchronize_rcu_bh();
-
- ahash_destroy(orig);
-
- return 0;
-}
-
-static int
-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;
- const struct type_pf_elem *d = value;
- struct hbucket *n;
- struct type_pf_elem *data;
- int ret = 0, i, j = AHASH_MAX(h) + 1;
- bool flag_exist = flags & IPSET_FLAG_EXIST;
- u32 key, multi = 0;
-
- if (h->elements >= h->maxelem)
- /* FIXME: when set is full, we slow down here */
- type_pf_expire(h);
- if (h->elements >= h->maxelem)
- return -IPSET_ERR_HASH_FULL;
-
- rcu_read_lock_bh();
- t = rcu_dereference_bh(h->table);
- key = HKEY(d, h->initval, t->htable_bits);
- n = hbucket(t, key);
- for (i = 0; i < n->pos; i++) {
- data = ahash_tdata(n, i);
- if (type_pf_data_equal(data, d, &multi)) {
- if (type_pf_data_expired(data) || flag_exist)
- j = i;
- else {
- ret = -IPSET_ERR_EXIST;
- goto out;
- }
- } else if (j == AHASH_MAX(h) + 1 &&
- type_pf_data_expired(data))
- j = i;
- }
- if (j != AHASH_MAX(h) + 1) {
- data = ahash_tdata(n, j);
-#ifdef IP_SET_HASH_WITH_NETS
- del_cidr(h, data->cidr, HOST_MASK);
- add_cidr(h, d->cidr, HOST_MASK);
-#endif
- type_pf_data_copy(data, d);
- type_pf_data_timeout_set(data, timeout);
- goto out;
- }
- TUNE_AHASH_MAX(h, multi);
- ret = type_pf_elem_tadd(n, d, AHASH_MAX(h), timeout);
- if (ret != 0) {
- if (ret == -EAGAIN)
- type_pf_data_next(h, d);
- goto out;
- }
-
-#ifdef IP_SET_HASH_WITH_NETS
- add_cidr(h, d->cidr, HOST_MASK);
-#endif
- h->elements++;
-out:
- rcu_read_unlock_bh();
- return ret;
-}
-
-static int
-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;
- const struct type_pf_elem *d = value;
- struct hbucket *n;
- int i;
- struct type_pf_elem *data;
- u32 key, multi = 0;
-
- key = HKEY(value, h->initval, t->htable_bits);
- n = hbucket(t, key);
- for (i = 0; i < n->pos; i++) {
- data = ahash_tdata(n, i);
- if (!type_pf_data_equal(data, d, &multi))
- continue;
- if (type_pf_data_expired(data))
- return -IPSET_ERR_EXIST;
- if (i != n->pos - 1)
- /* Not last one */
- type_pf_data_copy(data, ahash_tdata(n, n->pos - 1));
-
- n->pos--;
- h->elements--;
-#ifdef IP_SET_HASH_WITH_NETS
- del_cidr(h, d->cidr, HOST_MASK);
-#endif
- if (n->pos + AHASH_INIT_SIZE < n->size) {
- void *tmp = kzalloc((n->size - AHASH_INIT_SIZE)
- * sizeof(struct type_pf_telem),
- GFP_ATOMIC);
- if (!tmp)
- return 0;
- n->size -= AHASH_INIT_SIZE;
- memcpy(tmp, n->value,
- n->size * sizeof(struct type_pf_telem));
- kfree(n->value);
- n->value = tmp;
- }
- return 0;
- }
-
- return -IPSET_ERR_EXIST;
-}
-
-#ifdef IP_SET_HASH_WITH_NETS
-static int
-type_pf_ttest_cidrs(struct ip_set *set, struct type_pf_elem *d, u32 timeout)
-{
- struct ip_set_hash *h = set->data;
- struct htable *t = h->table;
- struct type_pf_elem *data;
- struct hbucket *n;
- int i, j = 0;
- u32 key, multi = 0;
- u8 host_mask = SET_HOST_MASK(set->family);
-
- for (; j < host_mask && h->nets[j].cidr && !multi; j++) {
- type_pf_data_netmask(d, h->nets[j].cidr);
- key = HKEY(d, h->initval, t->htable_bits);
- n = hbucket(t, key);
- for (i = 0; i < n->pos; i++) {
- data = ahash_tdata(n, i);
- if (type_pf_data_equal(data, d, &multi))
- return !type_pf_data_expired(data);
- }
- }
- return 0;
-}
-#endif
-
-static int
-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;
- struct type_pf_elem *data, *d = value;
- struct hbucket *n;
- int i;
- u32 key, multi = 0;
-
-#ifdef IP_SET_HASH_WITH_NETS
- if (d->cidr == SET_HOST_MASK(set->family))
- return type_pf_ttest_cidrs(set, d, timeout);
-#endif
- key = HKEY(d, h->initval, t->htable_bits);
- n = hbucket(t, key);
- for (i = 0; i < n->pos; i++) {
- data = ahash_tdata(n, i);
- if (type_pf_data_equal(data, d, &multi))
- return !type_pf_data_expired(data);
- }
- return 0;
-}
-
-static int
-type_pf_tlist(const struct ip_set *set,
- struct sk_buff *skb, struct netlink_callback *cb)
-{
- const struct ip_set_hash *h = set->data;
- const struct htable *t = h->table;
- struct nlattr *atd, *nested;
- const struct hbucket *n;
- const struct type_pf_elem *data;
- u32 first = cb->args[2];
- /* We assume that one hash bucket fills into one page */
- void *incomplete;
- int i;
-
- atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
- if (!atd)
- 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]);
- for (i = 0; i < n->pos; i++) {
- data = ahash_tdata(n, i);
- pr_debug("list %p %u\n", n, i);
- if (type_pf_data_expired(data))
- continue;
- pr_debug("do list %p %u\n", n, i);
- nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
- if (!nested) {
- if (cb->args[2] == first) {
- nla_nest_cancel(skb, atd);
- return -EMSGSIZE;
- } else
- goto nla_put_failure;
- }
- if (type_pf_data_tlist(skb, data))
- goto nla_put_failure;
- ipset_nest_end(skb, nested);
- }
- }
- ipset_nest_end(skb, atd);
- /* Set listing finished */
- cb->args[2] = 0;
-
- return 0;
-
-nla_put_failure:
- nlmsg_trim(skb, incomplete);
- ipset_nest_end(skb, atd);
- if (unlikely(first == cb->args[2])) {
- 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;
-}
-
-static const struct ip_set_type_variant type_pf_tvariant = {
- .kadt = type_pf_kadt,
- .uadt = type_pf_uadt,
- .adt = {
- [IPSET_ADD] = type_pf_tadd,
- [IPSET_DEL] = type_pf_tdel,
- [IPSET_TEST] = type_pf_ttest,
- },
- .destroy = type_pf_destroy,
- .flush = type_pf_flush,
- .head = type_pf_head,
- .list = type_pf_tlist,
- .resize = type_pf_tresize,
- .same_set = type_pf_same_set,
-};
-
-static void
-type_pf_gc(unsigned long ul_set)
-{
- struct ip_set *set = (struct ip_set *) ul_set;
- struct ip_set_hash *h = set->data;
-
- pr_debug("called\n");
- write_lock_bh(&set->lock);
- type_pf_expire(h);
- write_unlock_bh(&set->lock);
-
- h->gc.expires = jiffies + IPSET_GC_PERIOD(h->timeout) * HZ;
- add_timer(&h->gc);
-}
-
-static void
-type_pf_gc_init(struct ip_set *set)
-{
- struct ip_set_hash *h = set->data;
-
- init_timer(&h->gc);
- h->gc.data = (unsigned long) set;
- h->gc.function = type_pf_gc;
- h->gc.expires = jiffies + IPSET_GC_PERIOD(h->timeout) * HZ;
- add_timer(&h->gc);
- pr_debug("gc initialized, run in every %u\n",
- IPSET_GC_PERIOD(h->timeout));
-}
-
-#undef HKEY_DATALEN
-#undef HKEY
-#undef type_pf_data_equal
-#undef type_pf_data_isnull
-#undef type_pf_data_copy
-#undef type_pf_data_zero_out
-#undef type_pf_data_list
-#undef type_pf_data_tlist
-
-#undef type_pf_elem
-#undef type_pf_telem
-#undef type_pf_data_timeout
-#undef type_pf_data_expired
-#undef type_pf_data_netmask
-#undef type_pf_data_timeout_set
-
-#undef type_pf_elem_add
-#undef type_pf_add
-#undef type_pf_del
-#undef type_pf_test_cidrs
-#undef type_pf_test
-
-#undef type_pf_elem_tadd
-#undef type_pf_expire
-#undef type_pf_tadd
-#undef type_pf_tdel
-#undef type_pf_ttest_cidrs
-#undef type_pf_ttest
-
-#undef type_pf_resize
-#undef type_pf_tresize
-#undef type_pf_flush
-#undef type_pf_destroy
-#undef type_pf_head
-#undef type_pf_list
-#undef type_pf_tlist
-#undef type_pf_same_set
-#undef type_pf_kadt
-#undef type_pf_uadt
-#undef type_pf_gc
-#undef type_pf_gc_init
-#undef type_pf_variant
-#undef type_pf_tvariant
+++ /dev/null
-#ifndef __IP_SET_BITMAP_H
-#define __IP_SET_BITMAP_H
-
-/* Bitmap type specific error codes */
-enum {
- /* The element is out of the range of the set */
- IPSET_ERR_BITMAP_RANGE = IPSET_ERR_TYPE_SPECIFIC,
- /* The range exceeds the size limit of the set type */
- IPSET_ERR_BITMAP_RANGE_SIZE,
-};
-
-#ifdef __KERNEL__
-#define IPSET_BITMAP_MAX_RANGE 0x0000FFFF
-
-/* Common functions */
-
-static inline u32
-range_to_mask(u32 from, u32 to, u8 *bits)
-{
- u32 mask = 0xFFFFFFFE;
-
- *bits = 32;
- while (--(*bits) > 0 && mask && (to & mask) != from)
- mask <<= 1;
-
- return mask;
-}
-
-#endif /* __KERNEL__ */
-
-#endif /* __IP_SET_BITMAP_H */
+++ /dev/null
-/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
- * Patrick Schaaf <bof@bof.de>
- * Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/* Kernel module implementing an IP set type: the bitmap:ip type */
-
-#include <linux/module.h>
-#include <linux/ip.h>
-#include <linux/skbuff.h>
-#include <linux/errno.h>
-#include <linux/bitops.h>
-#include <linux/spinlock.h>
-#include <linux/netlink.h>
-#include <linux/jiffies.h>
-#include <linux/timer.h>
-#include <net/netlink.h>
-#include <net/tcp.h>
-
-#include "pfxlen.h"
-#include "ip_set.h"
-#include "ip_set_bitmap.h"
-#define IP_SET_BITMAP_TIMEOUT
-#include "ip_set_timeout.h"
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
-MODULE_DESCRIPTION("bitmap:ip type of IP sets");
-MODULE_ALIAS("ip_set_bitmap:ip");
-
-/* Type structure */
-struct bitmap_ip {
- void *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 */
-};
-
-/* 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 int
-bitmap_ip_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
-{
- const struct bitmap_ip *map = set->data;
- u16 id = *(u16 *)value;
-
- return !!test_bit(id, map->members);
-}
-
-static int
-bitmap_ip_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
-{
- 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 int
-bitmap_ip_del(struct ip_set *set, void *value, u32 timeout, u32 flags)
-{
- 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, u32 flags)
-{
- 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, u32 flags)
-{
- struct bitmap_ip *map = set->data;
- unsigned long *members = map->members;
- u16 id = *(u16 *)value;
-
- if (ip_set_timeout_test(members[id]) && !(flags & IPSET_FLAG_EXIST))
- 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, u32 flags)
-{
- 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,
- const struct xt_action_param *par,
- enum ipset_adt adt, const struct ip_set_adt_opt *opt)
-{
- struct bitmap_ip *map = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- u32 ip;
-
- ip = ntohl(ip4addr(skb, opt->flags & IPSET_DIM_ONE_SRC));
- if (ip < map->first_ip || ip > map->last_ip)
- return -IPSET_ERR_BITMAP_RANGE;
-
- ip = ip_to_id(map, ip);
-
- return adtfn(set, &ip, opt_timeout(opt, map), opt->cmdflags);
-}
-
-static int
-bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
-{
- struct bitmap_ip *map = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- u32 timeout = map->timeout;
- u32 ip, ip_to, id;
- int ret = 0;
-
- 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 (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) {
- id = ip_to_id(map, ip);
- return adtfn(set, &id, timeout, flags);
- }
-
- 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_set_mask_from_to(ip, ip_to, cidr);
- } else
- ip_to = ip;
-
- if (ip_to > map->last_ip)
- return -IPSET_ERR_BITMAP_RANGE;
-
- for (; !before(ip_to, ip); ip += map->hosts) {
- id = ip_to_id(map, ip);
- ret = adtfn(set, &id, timeout, flags);
-
- if (ret && !ip_set_eexist(ret, flags))
- return ret;
- else
- ret = 0;
- }
- return ret;
-}
-
-static void
-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);
-
- set->data = NULL;
-}
-
-static void
-bitmap_ip_flush(struct ip_set *set)
-{
- struct bitmap_ip *map = set->data;
-
- memset(map->members, 0, map->memsize);
-}
-
-static int
-bitmap_ip_head(struct ip_set *set, struct sk_buff *skb)
-{
- const struct bitmap_ip *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_REFERENCES, htonl(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 -EMSGSIZE;
-}
-
-static bool
-bitmap_ip_same_set(const struct ip_set *a, const struct ip_set *b)
-{
- const struct bitmap_ip *x = a->data;
- const struct bitmap_ip *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 = {
- .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,
- .list = bitmap_ip_list,
- .same_set = bitmap_ip_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 *map = set->data;
- unsigned long *table = map->members;
- u32 id;
-
- /* We run parallel with other readers (test element)
- * but adding/deleting new entries is locked out */
- read_lock_bh(&set->lock);
- for (id = 0; id < map->elements; id++)
- if (ip_set_timeout_expired(table[id]))
- table[id] = IPSET_ELEM_UNSET;
- read_unlock_bh(&set->lock);
-
- map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
- add_timer(&map->gc);
-}
-
-static void
-bitmap_ip_gc_init(struct ip_set *set)
-{
- struct bitmap_ip *map = set->data;
-
- init_timer(&map->gc);
- map->gc.data = (unsigned long) set;
- map->gc.function = bitmap_ip_gc;
- map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
- add_timer(&map->gc);
-}
-
-/* Create bitmap:ip type of sets */
-
-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);
- if (!map->members)
- return false;
- map->first_ip = first_ip;
- map->last_ip = last_ip;
- map->elements = elements;
- map->hosts = hosts;
- map->netmask = netmask;
- map->timeout = IPSET_NO_TIMEOUT;
-
- set->data = map;
- set->family = NFPROTO_IPV4;
-
- return true;
-}
-
-static int
-bitmap_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
-{
- struct bitmap_ip *map;
- u32 first_ip, last_ip, hosts, elements;
- u8 netmask = 32;
- int ret;
-
- if (unlikely(!tb[IPSET_ATTR_IP] ||
- !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
- return -IPSET_ERR_PROTOCOL;
-
- ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &first_ip);
- if (ret)
- return ret;
-
- if (tb[IPSET_ATTR_IP_TO]) {
- ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &last_ip);
- if (ret)
- return ret;
- if (first_ip > last_ip) {
- u32 tmp = first_ip;
-
- first_ip = last_ip;
- last_ip = tmp;
- }
- } else if (tb[IPSET_ATTR_CIDR]) {
- u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
-
- if (cidr >= 32)
- return -IPSET_ERR_INVALID_CIDR;
- ip_set_mask_from_to(first_ip, last_ip, cidr);
- } else
- return -IPSET_ERR_PROTOCOL;
-
- if (tb[IPSET_ATTR_NETMASK]) {
- netmask = nla_get_u8(tb[IPSET_ATTR_NETMASK]);
-
- if (netmask > 32)
- return -IPSET_ERR_INVALID_NETMASK;
-
- first_ip &= ip_set_hostmask(netmask);
- last_ip |= ~ip_set_hostmask(netmask);
- }
-
- if (netmask == 32) {
- hosts = 1;
- elements = last_ip - first_ip + 1;
- } else {
- u8 mask_bits;
- u32 mask;
-
- mask = range_to_mask(first_ip, last_ip, &mask_bits);
-
- if ((!mask && (first_ip || last_ip != 0xFFFFFFFF)) ||
- netmask <= mask_bits)
- return -IPSET_ERR_BITMAP_RANGE;
-
- pr_debug("mask_bits %u, netmask %u\n", mask_bits, netmask);
- hosts = 2 << (32 - netmask - 1);
- elements = 2 << (netmask - mask_bits - 1);
- }
- if (elements > IPSET_BITMAP_MAX_RANGE + 1)
- return -IPSET_ERR_BITMAP_RANGE_SIZE;
-
- pr_debug("hosts %u, elements %u\n", hosts, elements);
-
- map = kzalloc(sizeof(*map), GFP_KERNEL);
- if (!map)
- return -ENOMEM;
-
- if (tb[IPSET_ATTR_TIMEOUT]) {
- map->memsize = elements * sizeof(unsigned long);
-
- 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_tip;
-
- bitmap_ip_gc_init(set);
- } else {
- map->memsize = bitmap_bytes(0, elements - 1);
-
- if (!init_map_ip(set, map, first_ip, last_ip,
- elements, hosts, netmask)) {
- kfree(map);
- return -ENOMEM;
- }
-
- set->variant = &bitmap_ip;
- }
- return 0;
-}
-
-static struct ip_set_type bitmap_ip_type __read_mostly = {
- .name = "bitmap:ip",
- .protocol = IPSET_PROTOCOL,
- .features = IPSET_TYPE_IP,
- .dimension = IPSET_DIM_ONE,
- .family = NFPROTO_IPV4,
- .revision_min = 0,
- .revision_max = 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,
-};
-
-static int __init
-bitmap_ip_init(void)
-{
- return ip_set_type_register(&bitmap_ip_type);
-}
-
-static void __exit
-bitmap_ip_fini(void)
-{
- ip_set_type_unregister(&bitmap_ip_type);
-}
-
-module_init(bitmap_ip_init);
-module_exit(bitmap_ip_fini);
+++ /dev/null
-/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
- * Patrick Schaaf <bof@bof.de>
- * Martin Josefsson <gandalf@wlug.westbo.se>
- * Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/* Kernel module implementing an IP set type: the bitmap:ip,mac type */
-
-#include <linux/module.h>
-#include <linux/ip.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/errno.h>
-#include <linux/if_ether.h>
-#include <linux/netlink.h>
-#include <linux/jiffies.h>
-#include <linux/timer.h>
-#include <net/netlink.h>
-
-#include "pfxlen.h"
-#include "ip_set.h"
-#include "ip_set_timeout.h"
-#include "ip_set_bitmap.h"
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
-MODULE_DESCRIPTION("bitmap:ip,mac type of IP sets");
-MODULE_ALIAS("ip_set_bitmap:ip,mac");
-
-enum {
- MAC_EMPTY, /* element is not set */
- MAC_FILLED, /* element is set with MAC */
- MAC_UNSET, /* element is set, without MAC */
-};
-
-/* Type structure */
-struct bitmap_ipmac {
- void *members; /* the set members */
- u32 first_ip; /* host byte order, included in range */
- u32 last_ip; /* host byte order, included in range */
- u32 timeout; /* timeout value */
- struct timer_list gc; /* garbage collector */
- size_t dsize; /* size of element */
-};
-
-/* ADT structure for generic function args */
-struct ipmac {
- u32 id; /* id in array */
- unsigned char *ether; /* ethernet address */
-};
-
-/* Member element without and with timeout */
-
-struct ipmac_elem {
- unsigned char ether[ETH_ALEN];
- unsigned char match;
-} __attribute__ ((aligned));
-
-struct ipmac_telem {
- unsigned char ether[ETH_ALEN];
- unsigned char match;
- unsigned long timeout;
-} __attribute__ ((aligned));
-
-static inline void *
-bitmap_ipmac_elem(const struct bitmap_ipmac *map, u32 id)
-{
- return (void *)((char *)map->members + id * map->dsize);
-}
-
-static inline bool
-bitmap_timeout(const struct bitmap_ipmac *map, u32 id)
-{
- const struct ipmac_telem *elem = bitmap_ipmac_elem(map, id);
-
- return ip_set_timeout_test(elem->timeout);
-}
-
-static inline bool
-bitmap_expired(const struct bitmap_ipmac *map, u32 id)
-{
- const struct ipmac_telem *elem = bitmap_ipmac_elem(map, id);
-
- return ip_set_timeout_expired(elem->timeout);
-}
-
-static inline int
-bitmap_ipmac_exist(const struct ipmac_telem *elem)
-{
- return elem->match == MAC_UNSET ||
- (elem->match == MAC_FILLED &&
- !ip_set_timeout_expired(elem->timeout));
-}
-
-/* Base variant */
-
-static int
-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;
- const struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id);
-
- switch (elem->match) {
- case MAC_UNSET:
- /* Trigger kernel to fill out the ethernet address */
- return -EAGAIN;
- case MAC_FILLED:
- return data->ether == NULL ||
- compare_ether_addr(data->ether, elem->ether) == 0;
- }
- return 0;
-}
-
-static int
-bitmap_ipmac_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
-{
- struct bitmap_ipmac *map = set->data;
- const struct ipmac *data = value;
- struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id);
-
- switch (elem->match) {
- case MAC_UNSET:
- if (!data->ether)
- /* Already added without ethernet address */
- return -IPSET_ERR_EXIST;
- /* Fill the MAC address */
- memcpy(elem->ether, data->ether, ETH_ALEN);
- elem->match = MAC_FILLED;
- break;
- case MAC_FILLED:
- return -IPSET_ERR_EXIST;
- case MAC_EMPTY:
- if (data->ether) {
- memcpy(elem->ether, data->ether, ETH_ALEN);
- elem->match = MAC_FILLED;
- } else
- elem->match = MAC_UNSET;
- }
-
- return 0;
-}
-
-static int
-bitmap_ipmac_del(struct ip_set *set, void *value, u32 timeout, u32 flags)
-{
- struct bitmap_ipmac *map = set->data;
- const struct ipmac *data = value;
- struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id);
-
- if (elem->match == MAC_EMPTY)
- return -IPSET_ERR_EXIST;
-
- elem->match = MAC_EMPTY;
-
- return 0;
-}
-
-static int
-bitmap_ipmac_list(const struct ip_set *set,
- struct sk_buff *skb, struct netlink_callback *cb)
-{
- const struct bitmap_ipmac *map = set->data;
- const struct ipmac_elem *elem;
- struct nlattr *atd, *nested;
- u32 id, first = cb->args[2];
- u32 last = map->last_ip - map->first_ip;
-
- atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
- if (!atd)
- return -EMSGSIZE;
- for (; cb->args[2] <= last; cb->args[2]++) {
- id = cb->args[2];
- elem = bitmap_ipmac_elem(map, id);
- if (elem->match == MAC_EMPTY)
- 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));
- if (elem->match == MAC_FILLED)
- NLA_PUT(skb, IPSET_ATTR_ETHER, ETH_ALEN,
- elem->ether);
- 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_ipmac_ttest(struct ip_set *set, void *value, u32 timeout, u32 flags)
-{
- const struct bitmap_ipmac *map = set->data;
- const struct ipmac *data = value;
- const struct ipmac_elem *elem = bitmap_ipmac_elem(map, data->id);
-
- switch (elem->match) {
- case MAC_UNSET:
- /* Trigger kernel to fill out the ethernet address */
- return -EAGAIN;
- case MAC_FILLED:
- return (data->ether == NULL ||
- compare_ether_addr(data->ether, elem->ether) == 0) &&
- !bitmap_expired(map, data->id);
- }
- return 0;
-}
-
-static int
-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 || flag_exist))
- /* Already added without ethernet address */
- return -IPSET_ERR_EXIST;
- /* Fill the MAC address and activate the timer */
- memcpy(elem->ether, data->ether, ETH_ALEN);
- elem->match = MAC_FILLED;
- if (timeout == map->timeout)
- /* Timeout was not specified, get stored one */
- timeout = elem->timeout;
- elem->timeout = ip_set_timeout_set(timeout);
- break;
- case MAC_FILLED:
- if (!(bitmap_expired(map, data->id) || flag_exist))
- return -IPSET_ERR_EXIST;
- /* Fall through */
- case MAC_EMPTY:
- if (data->ether) {
- memcpy(elem->ether, data->ether, ETH_ALEN);
- elem->match = MAC_FILLED;
- } else
- elem->match = MAC_UNSET;
- /* If MAC is unset yet, we store plain timeout value
- * because the timer is not activated yet
- * and we can reuse it later when MAC is filled out,
- * possibly by the kernel */
- elem->timeout = data->ether ? ip_set_timeout_set(timeout)
- : timeout;
- break;
- }
-
- return 0;
-}
-
-static int
-bitmap_ipmac_tdel(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);
-
- if (elem->match == MAC_EMPTY || bitmap_expired(map, data->id))
- return -IPSET_ERR_EXIST;
-
- elem->match = MAC_EMPTY;
-
- return 0;
-}
-
-static int
-bitmap_ipmac_tlist(const struct ip_set *set,
- struct sk_buff *skb, struct netlink_callback *cb)
-{
- const struct bitmap_ipmac *map = set->data;
- const struct ipmac_telem *elem;
- struct nlattr *atd, *nested;
- u32 id, first = cb->args[2];
- u32 timeout, last = map->last_ip - map->first_ip;
-
- atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
- if (!atd)
- return -EMSGSIZE;
- for (; cb->args[2] <= last; cb->args[2]++) {
- id = cb->args[2];
- elem = bitmap_ipmac_elem(map, id);
- if (!bitmap_ipmac_exist(elem))
- 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));
- if (elem->match == MAC_FILLED)
- NLA_PUT(skb, IPSET_ATTR_ETHER, ETH_ALEN,
- elem->ether);
- timeout = elem->match == MAC_UNSET ? elem->timeout
- : ip_set_timeout_get(elem->timeout);
- NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(timeout));
- ipset_nest_end(skb, nested);
- }
- ipset_nest_end(skb, atd);
- /* Set listing finished */
- cb->args[2] = 0;
-
- return 0;
-
-nla_put_failure:
- nla_nest_cancel(skb, nested);
- ipset_nest_end(skb, atd);
- return -EMSGSIZE;
-}
-
-static int
-bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
- const struct xt_action_param *par,
- enum ipset_adt adt, const struct ip_set_adt_opt *opt)
-{
- struct bitmap_ipmac *map = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- struct ipmac data;
-
- /* MAC can be src only */
- if (!(opt->flags & IPSET_DIM_TWO_SRC))
- return 0;
-
- data.id = ntohl(ip4addr(skb, opt->flags & IPSET_DIM_ONE_SRC));
- if (data.id < map->first_ip || data.id > map->last_ip)
- return -IPSET_ERR_BITMAP_RANGE;
-
- /* Backward compatibility: we don't check the second flag */
- if (skb_mac_header(skb) < skb->head ||
- (skb_mac_header(skb) + ETH_HLEN) > skb->data)
- return -EINVAL;
-
- data.id -= map->first_ip;
- data.ether = eth_hdr(skb)->h_source;
-
- return adtfn(set, &data, opt_timeout(opt, map), opt->cmdflags);
-}
-
-static int
-bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
-{
- const struct bitmap_ipmac *map = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- struct ipmac data;
- u32 timeout = map->timeout;
- int ret = 0;
-
- 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], &data.id);
- if (ret)
- return ret;
-
- if (data.id < map->first_ip || data.id > map->last_ip)
- return -IPSET_ERR_BITMAP_RANGE;
-
- if (tb[IPSET_ATTR_ETHER])
- data.ether = nla_data(tb[IPSET_ATTR_ETHER]);
- else
- data.ether = NULL;
-
- if (tb[IPSET_ATTR_TIMEOUT]) {
- if (!with_timeout(map->timeout))
- return -IPSET_ERR_TIMEOUT;
- timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
- }
-
- data.id -= map->first_ip;
-
- ret = adtfn(set, &data, timeout, flags);
-
- return ip_set_eexist(ret, flags) ? 0 : ret;
-}
-
-static void
-bitmap_ipmac_destroy(struct ip_set *set)
-{
- struct bitmap_ipmac *map = set->data;
-
- if (with_timeout(map->timeout))
- del_timer_sync(&map->gc);
-
- ip_set_free(map->members);
- kfree(map);
-
- set->data = NULL;
-}
-
-static void
-bitmap_ipmac_flush(struct ip_set *set)
-{
- struct bitmap_ipmac *map = set->data;
-
- memset(map->members, 0,
- (map->last_ip - map->first_ip + 1) * map->dsize);
-}
-
-static int
-bitmap_ipmac_head(struct ip_set *set, struct sk_buff *skb)
-{
- const struct bitmap_ipmac *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));
- 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));
- 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 -EMSGSIZE;
-}
-
-static bool
-bitmap_ipmac_same_set(const struct ip_set *a, const struct ip_set *b)
-{
- const struct bitmap_ipmac *x = a->data;
- const struct bitmap_ipmac *y = b->data;
-
- return x->first_ip == y->first_ip &&
- x->last_ip == y->last_ip &&
- x->timeout == y->timeout;
-}
-
-static const struct ip_set_type_variant bitmap_ipmac = {
- .kadt = bitmap_ipmac_kadt,
- .uadt = bitmap_ipmac_uadt,
- .adt = {
- [IPSET_ADD] = bitmap_ipmac_add,
- [IPSET_DEL] = bitmap_ipmac_del,
- [IPSET_TEST] = bitmap_ipmac_test,
- },
- .destroy = bitmap_ipmac_destroy,
- .flush = bitmap_ipmac_flush,
- .head = bitmap_ipmac_head,
- .list = bitmap_ipmac_list,
- .same_set = bitmap_ipmac_same_set,
-};
-
-static const struct ip_set_type_variant bitmap_tipmac = {
- .kadt = bitmap_ipmac_kadt,
- .uadt = bitmap_ipmac_uadt,
- .adt = {
- [IPSET_ADD] = bitmap_ipmac_tadd,
- [IPSET_DEL] = bitmap_ipmac_tdel,
- [IPSET_TEST] = bitmap_ipmac_ttest,
- },
- .destroy = bitmap_ipmac_destroy,
- .flush = bitmap_ipmac_flush,
- .head = bitmap_ipmac_head,
- .list = bitmap_ipmac_tlist,
- .same_set = bitmap_ipmac_same_set,
-};
-
-static void
-bitmap_ipmac_gc(unsigned long ul_set)
-{
- struct ip_set *set = (struct ip_set *) ul_set;
- struct bitmap_ipmac *map = set->data;
- struct ipmac_telem *elem;
- u32 id, last = map->last_ip - map->first_ip;
-
- /* We run parallel with other readers (test element)
- * but adding/deleting new entries is locked out */
- read_lock_bh(&set->lock);
- for (id = 0; id <= last; id++) {
- elem = bitmap_ipmac_elem(map, id);
- if (elem->match == MAC_FILLED &&
- ip_set_timeout_expired(elem->timeout))
- elem->match = MAC_EMPTY;
- }
- read_unlock_bh(&set->lock);
-
- map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
- add_timer(&map->gc);
-}
-
-static void
-bitmap_ipmac_gc_init(struct ip_set *set)
-{
- struct bitmap_ipmac *map = set->data;
-
- init_timer(&map->gc);
- map->gc.data = (unsigned long) set;
- map->gc.function = bitmap_ipmac_gc;
- map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
- add_timer(&map->gc);
-}
-
-/* Create bitmap:ip,mac type of sets */
-
-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);
- if (!map->members)
- return false;
- map->first_ip = first_ip;
- map->last_ip = last_ip;
- map->timeout = IPSET_NO_TIMEOUT;
-
- set->data = map;
- set->family = NFPROTO_IPV4;
-
- return true;
-}
-
-static int
-bitmap_ipmac_create(struct ip_set *set, struct nlattr *tb[],
- u32 flags)
-{
- u32 first_ip, last_ip, elements;
- struct bitmap_ipmac *map;
- int ret;
-
- if (unlikely(!tb[IPSET_ATTR_IP] ||
- !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
- return -IPSET_ERR_PROTOCOL;
-
- ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP], &first_ip);
- if (ret)
- return ret;
-
- if (tb[IPSET_ATTR_IP_TO]) {
- ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &last_ip);
- if (ret)
- return ret;
- if (first_ip > last_ip) {
- u32 tmp = first_ip;
-
- first_ip = last_ip;
- last_ip = tmp;
- }
- } else if (tb[IPSET_ATTR_CIDR]) {
- u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
-
- if (cidr >= 32)
- return -IPSET_ERR_INVALID_CIDR;
- ip_set_mask_from_to(first_ip, last_ip, cidr);
- } else
- return -IPSET_ERR_PROTOCOL;
-
- elements = last_ip - first_ip + 1;
-
- if (elements > IPSET_BITMAP_MAX_RANGE + 1)
- return -IPSET_ERR_BITMAP_RANGE_SIZE;
-
- map = kzalloc(sizeof(*map), GFP_KERNEL);
- if (!map)
- return -ENOMEM;
-
- if (tb[IPSET_ATTR_TIMEOUT]) {
- map->dsize = sizeof(struct ipmac_telem);
-
- if (!init_map_ipmac(set, map, first_ip, last_ip)) {
- kfree(map);
- return -ENOMEM;
- }
-
- map->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
-
- set->variant = &bitmap_tipmac;
-
- bitmap_ipmac_gc_init(set);
- } else {
- map->dsize = sizeof(struct ipmac_elem);
-
- if (!init_map_ipmac(set, map, first_ip, last_ip)) {
- kfree(map);
- return -ENOMEM;
- }
- set->variant = &bitmap_ipmac;
-
- }
- return 0;
-}
-
-static struct ip_set_type bitmap_ipmac_type = {
- .name = "bitmap:ip,mac",
- .protocol = IPSET_PROTOCOL,
- .features = IPSET_TYPE_IP | IPSET_TYPE_MAC,
- .dimension = IPSET_DIM_TWO,
- .family = NFPROTO_IPV4,
- .revision_min = 0,
- .revision_max = 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,
-};
-
-static int __init
-bitmap_ipmac_init(void)
-{
- return ip_set_type_register(&bitmap_ipmac_type);
-}
-
-static void __exit
-bitmap_ipmac_fini(void)
-{
- ip_set_type_unregister(&bitmap_ipmac_type);
-}
-
-module_init(bitmap_ipmac_init);
-module_exit(bitmap_ipmac_fini);
+++ /dev/null
-/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/* Kernel module implementing an IP set type: the bitmap:port type */
-
-#include <linux/module.h>
-#include <linux/ip.h>
-#include <linux/skbuff.h>
-#include <linux/errno.h>
-#include <linux/netlink.h>
-#include <linux/jiffies.h>
-#include <linux/timer.h>
-#include <net/netlink.h>
-
-#include "ip_set.h"
-#include "ip_set_bitmap.h"
-#include "ip_set_getport.h"
-#define IP_SET_BITMAP_TIMEOUT
-#include "ip_set_timeout.h"
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
-MODULE_DESCRIPTION("bitmap:port type of IP sets");
-MODULE_ALIAS("ip_set_bitmap:port");
-
-/* 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 */
-};
-
-/* Base variant */
-
-static int
-bitmap_port_test(struct ip_set *set, void *value, u32 timeout, u32 flags)
-{
- const struct bitmap_port *map = set->data;
- u16 id = *(u16 *)value;
-
- return !!test_bit(id, map->members);
-}
-
-static int
-bitmap_port_add(struct ip_set *set, void *value, u32 timeout, u32 flags)
-{
- struct bitmap_port *map = set->data;
- u16 id = *(u16 *)value;
-
- if (test_and_set_bit(id, map->members))
- return -IPSET_ERR_EXIST;
-
- return 0;
-}
-
-static int
-bitmap_port_del(struct ip_set *set, void *value, u32 timeout, u32 flags)
-{
- 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, u32 flags)
-{
- 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, u32 flags)
-{
- struct bitmap_port *map = set->data;
- unsigned long *members = map->members;
- u16 id = *(u16 *)value;
-
- if (ip_set_timeout_test(members[id]) && !(flags & IPSET_FLAG_EXIST))
- 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, u32 flags)
-{
- 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,
- const struct xt_action_param *par,
- enum ipset_adt adt, const struct ip_set_adt_opt *opt)
-{
- struct bitmap_port *map = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- __be16 __port;
- u16 port = 0;
-
- if (!ip_set_get_ip_port(skb, opt->family,
- opt->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;
-
- return adtfn(set, &port, opt_timeout(opt, map), opt->cmdflags);
-}
-
-static int
-bitmap_port_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
-{
- struct bitmap_port *map = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- u32 timeout = map->timeout;
- u32 port; /* wraparound */
- u16 id, port_to;
- int ret = 0;
-
- 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 (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) {
- id = port - map->first_port;
- return adtfn(set, &id, timeout, flags);
- }
-
- 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;
-
- for (; port <= port_to; port++) {
- id = port - map->first_port;
- ret = adtfn(set, &id, timeout, flags);
-
- if (ret && !ip_set_eexist(ret, flags))
- return ret;
- else
- ret = 0;
- }
- return ret;
-}
-
-static void
-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);
-
- set->data = NULL;
-}
-
-static void
-bitmap_port_flush(struct ip_set *set)
-{
- struct bitmap_port *map = set->data;
-
- memset(map->members, 0, map->memsize);
-}
-
-static int
-bitmap_port_head(struct ip_set *set, struct sk_buff *skb)
-{
- const struct bitmap_port *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_REFERENCES, htonl(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 -EMSGSIZE;
-}
-
-static bool
-bitmap_port_same_set(const struct ip_set *a, const struct ip_set *b)
-{
- const struct bitmap_port *x = a->data;
- const struct bitmap_port *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 = {
- .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,
- .list = bitmap_port_list,
- .same_set = bitmap_port_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 *map = set->data;
- unsigned long *table = map->members;
- u32 id; /* wraparound */
- u16 last = map->last_port - map->first_port;
-
- /* We run parallel with other readers (test element)
- * but adding/deleting new entries is locked out */
- read_lock_bh(&set->lock);
- for (id = 0; id <= last; id++)
- if (ip_set_timeout_expired(table[id]))
- table[id] = IPSET_ELEM_UNSET;
- read_unlock_bh(&set->lock);
-
- map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
- add_timer(&map->gc);
-}
-
-static void
-bitmap_port_gc_init(struct ip_set *set)
-{
- struct bitmap_port *map = set->data;
-
- init_timer(&map->gc);
- map->gc.data = (unsigned long) set;
- map->gc.function = bitmap_port_gc;
- map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
- add_timer(&map->gc);
-}
-
-/* Create bitmap:ip type of sets */
-
-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);
- 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 = NFPROTO_UNSPEC;
-
- return true;
-}
-
-static int
-bitmap_port_create(struct ip_set *set, struct nlattr *tb[],
- u32 flags)
-{
- struct bitmap_port *map;
- u16 first_port, last_port;
-
- 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)))
- return -IPSET_ERR_PROTOCOL;
-
- first_port = ip_set_get_h16(tb[IPSET_ATTR_PORT]);
- last_port = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
- if (first_port > last_port) {
- u16 tmp = first_port;
-
- first_port = last_port;
- last_port = tmp;
- }
-
- map = kzalloc(sizeof(*map), GFP_KERNEL);
- if (!map)
- return -ENOMEM;
-
- if (tb[IPSET_ATTR_TIMEOUT]) {
- map->memsize = (last_port - first_port + 1)
- * sizeof(unsigned long);
-
- 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_tport;
-
- bitmap_port_gc_init(set);
- } else {
- 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)) {
- kfree(map);
- return -ENOMEM;
- }
-
- set->variant = &bitmap_port;
- }
- return 0;
-}
-
-static struct ip_set_type bitmap_port_type = {
- .name = "bitmap:port",
- .protocol = IPSET_PROTOCOL,
- .features = IPSET_TYPE_PORT,
- .dimension = IPSET_DIM_ONE,
- .family = NFPROTO_UNSPEC,
- .revision_min = 0,
- .revision_max = 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,
-};
-
-static int __init
-bitmap_port_init(void)
-{
- return ip_set_type_register(&bitmap_port_type);
-}
-
-static void __exit
-bitmap_port_fini(void)
-{
- ip_set_type_unregister(&bitmap_port_type);
-}
-
-module_init(bitmap_port_init);
-module_exit(bitmap_port_fini);
+++ /dev/null
-/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
- * Patrick Schaaf <bof@bof.de>
- * Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/* Kernel module for IP set management */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/ip.h>
-#include <linux/skbuff.h>
-#include <linux/spinlock.h>
-#include <linux/netlink.h>
-#include <linux/rculist.h>
-#ifndef IPSET_IN_KERNEL_TREE
-#include <linux/version.h>
-#endif
-#include <net/netlink.h>
-
-#include <linux/netfilter.h>
-#include <linux/netfilter/x_tables.h>
-#include <linux/netfilter/nfnetlink.h>
-#include "ip_set.h"
-#include <net/genetlink.h>
-#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 */
-
-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 */
-
-#define STREQ(a, b) (strncmp(a, b, IPSET_MAXNAMELEN) == 0)
-
-static unsigned int max_sets;
-
-module_param(max_sets, int, 0600);
-MODULE_PARM_DESC(max_sets, "maximal number of sets");
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
-MODULE_DESCRIPTION("core IP set support");
-
-static struct genl_family ip_set_netlink_subsys;
-
-/*
- * The set types are implemented in modules and registered set types
- * can be found in ip_set_type_list. Adding/deleting types is
- * serialized by ip_set_type_mutex.
- */
-
-static inline void
-ip_set_type_lock(void)
-{
- mutex_lock(&ip_set_type_mutex);
-}
-
-static inline void
-ip_set_type_unlock(void)
-{
- mutex_unlock(&ip_set_type_mutex);
-}
-
-/* Register and deregister settype */
-
-static struct ip_set_type *
-find_set_type(const char *name, u8 family, u8 revision)
-{
- struct ip_set_type *type;
-
- list_for_each_entry_rcu(type, &ip_set_type_list, list)
- if (STREQ(type->name, name) &&
- (type->family == family || type->family == NFPROTO_UNSPEC) &&
- revision >= type->revision_min &&
- revision <= type->revision_max)
- return type;
- return NULL;
-}
-
-/* Unlock, try to load a set type module and lock again */
-static bool
-load_settype(const char *name)
-{
- 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);
- genl_lock();
- return false;
- }
- genl_lock();
- return true;
-}
-
-/* Find a set type and reference it */
-#define find_set_type_get(name, family, revision, found) \
- __find_set_type_get(name, family, revision, found, false)
-
-static int
-__find_set_type_get(const char *name, u8 family, u8 revision,
- struct ip_set_type **found, bool retry)
-{
- struct ip_set_type *type;
- int err;
-
- if (retry && !load_settype(name))
- return -IPSET_ERR_FIND_TYPE;
-
- rcu_read_lock();
- *found = find_set_type(name, family, revision);
- if (*found) {
- err = !try_module_get((*found)->me) ? -EFAULT : 0;
- goto unlock;
- }
- /* Make sure the type is already 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 retry ? -IPSET_ERR_FIND_TYPE :
- __find_set_type_get(name, family, revision, found, true);
-
-unlock:
- rcu_read_unlock();
- return err;
-}
-
-/* Find a given set type by name and family.
- * If we succeeded, the supported minimal and maximum revisions are
- * filled out.
- */
-#define find_set_type_minmax(name, family, min, max) \
- __find_set_type_minmax(name, family, min, max, false)
-
-static int
-__find_set_type_minmax(const char *name, u8 family, u8 *min, u8 *max,
- bool retry)
-{
- struct ip_set_type *type;
- bool found = false;
-
- if (retry && !load_settype(name))
- return -IPSET_ERR_FIND_TYPE;
-
- *min = 255; *max = 0;
- rcu_read_lock();
- list_for_each_entry_rcu(type, &ip_set_type_list, list)
- if (STREQ(type->name, name) &&
- (type->family == family || type->family == NFPROTO_UNSPEC)) {
- found = true;
- if (type->revision_min < *min)
- *min = type->revision_min;
- if (type->revision_max > *max)
- *max = type->revision_max;
- }
- rcu_read_unlock();
- if (found)
- return 0;
-
- return retry ? -IPSET_ERR_FIND_TYPE :
- __find_set_type_minmax(name, family, min, max, true);
-}
-
-#define family_name(f) ((f) == NFPROTO_IPV4 ? "inet" : \
- (f) == NFPROTO_IPV6 ? "inet6" : "any")
-
-/* Register a set type structure. The type is identified by
- * the unique triple of name, family and revision.
- */
-int
-ip_set_type_register(struct ip_set_type *type)
-{
- int ret = 0;
-
- if (type->protocol != IPSET_PROTOCOL) {
- pr_warning("ip_set type %s, family %s, revision %u:%u uses "
- "wrong protocol version %u (want %u)\n",
- type->name, family_name(type->family),
- type->revision_min, type->revision_max,
- type->protocol, IPSET_PROTOCOL);
- return -EINVAL;
- }
-
- ip_set_type_lock();
- if (find_set_type(type->name, type->family, type->revision_min)) {
- /* Duplicate! */
- pr_warning("ip_set type %s, family %s with revision min %u "
- "already registered!\n", type->name,
- family_name(type->family), type->revision_min);
- ret = -EINVAL;
- goto unlock;
- }
- list_add_rcu(&type->list, &ip_set_type_list);
- pr_debug("type %s, family %s, revision %u:%u registered.\n",
- type->name, family_name(type->family),
- type->revision_min, type->revision_max);
-unlock:
- ip_set_type_unlock();
- return ret;
-}
-EXPORT_SYMBOL_GPL(ip_set_type_register);
-
-/* Unregister a set type. There's a small race with ip_set_create */
-void
-ip_set_type_unregister(struct ip_set_type *type)
-{
- ip_set_type_lock();
- if (!find_set_type(type->name, type->family, type->revision_min)) {
- pr_warning("ip_set type %s, family %s with revision min %u "
- "not registered\n", type->name,
- family_name(type->family), type->revision_min);
- goto unlock;
- }
- list_del_rcu(&type->list);
- pr_debug("type %s, family %s with revision min %u unregistered.\n",
- type->name, family_name(type->family), type->revision_min);
-unlock:
- ip_set_type_unlock();
-
- synchronize_rcu();
-}
-EXPORT_SYMBOL_GPL(ip_set_type_unregister);
-
-/* Utility functions */
-void *
-ip_set_alloc(size_t size)
-{
- void *members = NULL;
-
- if (size < KMALLOC_MAX_SIZE)
- members = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
-
- if (members) {
- pr_debug("%p: allocated with kmalloc\n", members);
- return members;
- }
-
-#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);
-
- return members;
-}
-EXPORT_SYMBOL_GPL(ip_set_alloc);
-
-void
-ip_set_free(void *members)
-{
- pr_debug("%p: free with %s\n", members,
- is_vmalloc_addr(members) ? "vfree" : "kfree");
- if (is_vmalloc_addr(members))
- vfree(members);
- else
- kfree(members);
-}
-EXPORT_SYMBOL_GPL(ip_set_free);
-
-static inline bool
-flag_nested(const struct nlattr *nla)
-{
- return nla->nla_type & NLA_F_NESTED;
-}
-
-static const struct nla_policy ipaddr_policy[IPSET_ATTR_IPADDR_MAX + 1] = {
- [IPSET_ATTR_IPADDR_IPV4] = { .type = NLA_U32 },
- [IPSET_ATTR_IPADDR_IPV6] = { .type = NLA_BINARY,
- .len = sizeof(struct in6_addr) },
-};
-
-int
-ip_set_get_ipaddr4(struct nlattr *nla, __be32 *ipaddr)
-{
- struct nlattr *tb[IPSET_ATTR_IPADDR_MAX+1];
-
- if (unlikely(!flag_nested(nla)))
- return -IPSET_ERR_PROTOCOL;
- 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;
-
- *ipaddr = nla_get_be32(tb[IPSET_ATTR_IPADDR_IPV4]);
- return 0;
-}
-EXPORT_SYMBOL_GPL(ip_set_get_ipaddr4);
-
-int
-ip_set_get_ipaddr6(struct nlattr *nla, union nf_inet_addr *ipaddr)
-{
- struct nlattr *tb[IPSET_ATTR_IPADDR_MAX+1];
-
- if (unlikely(!flag_nested(nla)))
- return -IPSET_ERR_PROTOCOL;
-
- 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;
-
- memcpy(ipaddr, nla_data(tb[IPSET_ATTR_IPADDR_IPV6]),
- sizeof(struct in6_addr));
- return 0;
-}
-EXPORT_SYMBOL_GPL(ip_set_get_ipaddr6);
-
-/*
- * Creating/destroying/renaming/swapping affect the existence and
- * the properties of a set. All of these can be executed from userspace
- * only and serialized by the nfnl mutex indirectly from nfnetlink.
- *
- * Sets are identified by their index in ip_set_list and the index
- * is used by the external references (set/SET netfilter modules).
- *
- * The set behind an index may change by swapping only, from userspace.
- */
-
-static inline void
-__ip_set_get(ip_set_id_t index)
-{
- 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)
-{
- 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);
-}
-
-/*
- * Add, del and test set entries from kernel.
- *
- * The set behind the index must exist and must be referenced
- * so it can't be destroyed (or changed) under our foot.
- */
-
-int
-ip_set_test(ip_set_id_t index, const struct sk_buff *skb,
- const struct xt_action_param *par,
- const struct ip_set_adt_opt *opt)
-{
- struct ip_set *set = ip_set_list[index];
- int ret = 0;
-
- BUG_ON(set == NULL);
- pr_debug("set %s, index %u\n", set->name, index);
-
- if (opt->dim < set->type->dimension ||
- !(opt->family == set->family || set->family == NFPROTO_UNSPEC))
- return 0;
-
- read_lock_bh(&set->lock);
- ret = set->variant->kadt(set, skb, par, IPSET_TEST, opt);
- read_unlock_bh(&set->lock);
-
- if (ret == -EAGAIN) {
- /* Type requests element to be completed */
- pr_debug("element must be competed, ADD is triggered\n");
- write_lock_bh(&set->lock);
- set->variant->kadt(set, skb, par, IPSET_ADD, opt);
- write_unlock_bh(&set->lock);
- ret = 1;
- }
-
- /* Convert error codes to nomatch */
- return (ret < 0 ? 0 : ret);
-}
-EXPORT_SYMBOL_GPL(ip_set_test);
-
-int
-ip_set_add(ip_set_id_t index, const struct sk_buff *skb,
- const struct xt_action_param *par,
- const struct ip_set_adt_opt *opt)
-{
- struct ip_set *set = ip_set_list[index];
- int ret;
-
- BUG_ON(set == NULL);
- pr_debug("set %s, index %u\n", set->name, index);
-
- if (opt->dim < set->type->dimension ||
- !(opt->family == set->family || set->family == NFPROTO_UNSPEC))
- return 0;
-
- write_lock_bh(&set->lock);
- ret = set->variant->kadt(set, skb, par, IPSET_ADD, opt);
- write_unlock_bh(&set->lock);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(ip_set_add);
-
-int
-ip_set_del(ip_set_id_t index, const struct sk_buff *skb,
- const struct xt_action_param *par,
- const struct ip_set_adt_opt *opt)
-{
- struct ip_set *set = ip_set_list[index];
- int ret = 0;
-
- BUG_ON(set == NULL);
- pr_debug("set %s, index %u\n", set->name, index);
-
- if (opt->dim < set->type->dimension ||
- !(opt->family == set->family || set->family == NFPROTO_UNSPEC))
- return 0;
-
- write_lock_bh(&set->lock);
- ret = set->variant->kadt(set, skb, par, IPSET_DEL, opt);
- write_unlock_bh(&set->lock);
-
- return ret;
-}
-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.
- *
- */
-ip_set_id_t
-ip_set_get_byname(const char *name, struct ip_set **set)
-{
- ip_set_id_t i, index = IPSET_INVALID_ID;
- struct ip_set *s;
-
- for (i = 0; i < ip_set_max; i++) {
- s = ip_set_list[i];
- if (s != NULL && STREQ(s->name, name)) {
- __ip_set_get(i);
- index = i;
- *set = s;
- }
- }
-
- return index;
-}
-EXPORT_SYMBOL_GPL(ip_set_get_byname);
-
-/*
- * If the given set pointer points to a valid set, decrement
- * reference count by 1. The caller shall not assume the index
- * to be valid, after calling this function.
- *
- */
-void
-ip_set_put_byindex(ip_set_id_t index)
-{
- if (ip_set_list[index] != NULL)
- __ip_set_put(index);
-}
-EXPORT_SYMBOL_GPL(ip_set_put_byindex);
-
-/*
- * Get the name of a set behind a set index.
- * We assume the set is referenced, so it does exist and
- * can't be destroyed. The set cannot be renamed due to
- * the referencing either.
- *
- */
-const char *
-ip_set_name_byindex(ip_set_id_t index)
-{
- const struct ip_set *set = ip_set_list[index];
-
- BUG_ON(set == NULL);
- BUG_ON(set->ref == 0);
-
- /* Referenced, so it's safe */
- return set->name;
-}
-EXPORT_SYMBOL_GPL(ip_set_name_byindex);
-
-/*
- * Routines to call by external subsystems, which do not
- * call nfnl_lock for us.
- */
-
-/*
- * 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 is used in the function.
- */
-ip_set_id_t
-ip_set_nfnl_get(const char *name)
-{
- struct ip_set *s;
- ip_set_id_t index;
-
- genl_lock();
- index = ip_set_get_byname(name, &s);
- genl_unlock();
-
- return index;
-}
-EXPORT_SYMBOL_GPL(ip_set_nfnl_get);
-
-/*
- * Find set by index, reference it once. The reference makes sure the
- * thing pointed to, does not go away under our feet.
- *
- * The nfnl mutex is used in the function.
- */
-ip_set_id_t
-ip_set_nfnl_get_byindex(ip_set_id_t index)
-{
- if (index > ip_set_max)
- return IPSET_INVALID_ID;
-
- genl_lock();
- if (ip_set_list[index])
- __ip_set_get(index);
- else
- index = IPSET_INVALID_ID;
- genl_unlock();
-
- return index;
-}
-EXPORT_SYMBOL_GPL(ip_set_nfnl_get_byindex);
-
-/*
- * If the given set pointer points to a valid set, decrement
- * reference count by 1. The caller shall not assume the index
- * to be valid, after calling this function.
- *
- * The nfnl mutex is used in the function.
- */
-void
-ip_set_nfnl_put(ip_set_id_t index)
-{
- genl_lock();
- ip_set_put_byindex(index);
- genl_unlock();
-}
-EXPORT_SYMBOL_GPL(ip_set_nfnl_put);
-
-/*
- * Communication protocol with userspace over netlink.
- *
- * The commands are serialized by the nfnl mutex.
- */
-
-static inline bool
-protocol_failed(struct nlattr *const *tb)
-{
- return !tb[IPSET_ATTR_PROTOCOL] ||
- nla_get_u8(tb[IPSET_ATTR_PROTOCOL]) != IPSET_PROTOCOL;
-}
-
-static inline u32
-flag_exist(const struct genlmsghdr *ghdr)
-{
- return ghdr->reserved & NLM_F_EXCL ? 0 : IPSET_FLAG_EXIST;
-}
-
-static struct genlmsg_buf *
-start_msg(struct sk_buff *skb, u32 pid, u32 seq, unsigned int flags,
- enum ipset_cmd cmd)
-{
- struct genlmsg_buf *nlh;
-
- nlh = genlmsg_put(skb, pid, seq, &ip_set_netlink_subsys, flags, cmd);
- if (nlh == NULL)
- return NULL;
- return nlh;
-}
-
-/* Create a set */
-
-static const struct nla_policy ip_set_create_policy[IPSET_ATTR_CMD_MAX + 1] = {
- [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 },
- [IPSET_ATTR_SETNAME] = { .type = NLA_NUL_STRING,
- .len = IPSET_MAXNAMELEN - 1 },
- [IPSET_ATTR_TYPENAME] = { .type = NLA_NUL_STRING,
- .len = IPSET_MAXNAMELEN - 1},
- [IPSET_ATTR_REVISION] = { .type = NLA_U8 },
- [IPSET_ATTR_FAMILY] = { .type = NLA_U8 },
- [IPSET_ATTR_DATA] = { .type = NLA_NESTED },
-};
-
-static ip_set_id_t
-find_set_id(const char *name)
-{
- ip_set_id_t i, index = IPSET_INVALID_ID;
- const struct ip_set *set;
-
- for (i = 0; index == IPSET_INVALID_ID && i < ip_set_max; i++) {
- set = ip_set_list[i];
- if (set != NULL && STREQ(set->name, name))
- index = i;
- }
- return index;
-}
-
-static inline struct ip_set *
-find_set(const char *name)
-{
- ip_set_id_t index = find_set_id(name);
-
- return index == IPSET_INVALID_ID ? NULL : ip_set_list[index];
-}
-
-static int
-find_free_id(const char *name, ip_set_id_t *index, struct ip_set **set)
-{
- ip_set_id_t i;
-
- *index = IPSET_INVALID_ID;
- for (i = 0; i < ip_set_max; i++) {
- if (ip_set_list[i] == NULL) {
- if (*index == IPSET_INVALID_ID)
- *index = i;
- } else if (STREQ(name, ip_set_list[i]->name)) {
- /* Name clash */
- *set = ip_set_list[i];
- return -EEXIST;
- }
- }
- if (*index == IPSET_INVALID_ID)
- /* No free slot remained */
- return -IPSET_ERR_MAX_SETS;
- return 0;
-}
-
-static int
-ip_set_create(struct sk_buff *skb, struct genl_info *info)
-{
- struct nlattr *const *attr = info->attrs;
- 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;
- u8 family, revision;
- u32 flags = flag_exist(info->genlhdr);
- int ret = 0;
-
- if (unlikely(protocol_failed(attr) ||
- attr[IPSET_ATTR_SETNAME] == NULL ||
- attr[IPSET_ATTR_TYPENAME] == NULL ||
- attr[IPSET_ATTR_REVISION] == NULL ||
- attr[IPSET_ATTR_FAMILY] == NULL ||
- (attr[IPSET_ATTR_DATA] != NULL &&
- !flag_nested(attr[IPSET_ATTR_DATA]))))
- return -IPSET_ERR_PROTOCOL;
-
- name = nla_data(attr[IPSET_ATTR_SETNAME]);
- typename = nla_data(attr[IPSET_ATTR_TYPENAME]);
- family = nla_get_u8(attr[IPSET_ATTR_FAMILY]);
- revision = nla_get_u8(attr[IPSET_ATTR_REVISION]);
- pr_debug("setname: %s, typename: %s, family: %s, revision: %u\n",
- name, typename, family_name(family), revision);
-
- /*
- * First, and without any locks, allocate and initialize
- * a normal base set structure.
- */
- set = kzalloc(sizeof(struct ip_set), GFP_KERNEL);
- if (!set)
- return -ENOMEM;
- rwlock_init(&set->lock);
- strlcpy(set->name, name, IPSET_MAXNAMELEN);
- set->family = family;
- set->revision = revision;
-
- /*
- * Next, check that we know the type, and take
- * a reference on the type, to make sure it stays available
- * while constructing our new set.
- *
- * After referencing the type, we try to create the type
- * specific part of the set without holding any locks.
- */
- ret = find_set_type_get(typename, family, revision, &(set->type));
- if (ret)
- goto out;
-
- /*
- * Without holding any locks, create private part.
- */
- 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;
-
- /* BTW, ret==0 here. */
-
- /*
- * Here, we have a valid, constructed set and we are protected
- * 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 */
- if (ret == -EEXIST &&
- (flags & IPSET_FLAG_EXIST) &&
- STREQ(set->type->name, clash->type->name) &&
- set->type->family == clash->type->family &&
- set->type->revision_min == clash->type->revision_min &&
- set->type->revision_max == clash->type->revision_max &&
- set->variant->same_set(set, clash))
- ret = 0;
- goto cleanup;
- }
-
- /*
- * Finally! Add our shiny new set to the list, and be done.
- */
- pr_debug("create: '%s' created with index %u!\n", set->name, index);
- ip_set_list[index] = set;
-
- return ret;
-
-cleanup:
- set->variant->destroy(set);
-put_out:
- module_put(set->type->me);
-out:
- kfree(set);
- return ret;
-}
-
-/* Destroy sets */
-
-static const struct nla_policy
-ip_set_setname_policy[IPSET_ATTR_CMD_MAX + 1] = {
- [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 },
- [IPSET_ATTR_SETNAME] = { .type = NLA_NUL_STRING,
- .len = IPSET_MAXNAMELEN - 1 },
-};
-
-static void
-ip_set_destroy_set(ip_set_id_t index)
-{
- struct ip_set *set = ip_set_list[index];
-
- pr_debug("set: %s\n", set->name);
- ip_set_list[index] = NULL;
-
- /* Must call it without holding any lock */
- set->variant->destroy(set);
- module_put(set->type->me);
- kfree(set);
-}
-
-static int
-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;
-
- /* 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 && 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) {
- 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 */
-
-static void
-ip_set_flush_set(struct ip_set *set)
-{
- pr_debug("set: %s\n", set->name);
-
- write_lock_bh(&set->lock);
- set->variant->flush(set);
- write_unlock_bh(&set->lock);
-}
-
-static int
-ip_set_flush(struct sk_buff *skb, struct genl_info *info)
-{
- struct nlattr *const *attr = info->attrs;
- ip_set_id_t i;
-
- if (unlikely(protocol_failed(attr)))
- return -IPSET_ERR_PROTOCOL;
-
- if (!attr[IPSET_ATTR_SETNAME]) {
- for (i = 0; i < ip_set_max; i++)
- if (ip_set_list[i] != NULL)
- ip_set_flush_set(ip_set_list[i]);
- } else {
- i = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME]));
- if (i == IPSET_INVALID_ID)
- return -ENOENT;
-
- ip_set_flush_set(ip_set_list[i]);
- }
-
- return 0;
-}
-
-/* Rename a set */
-
-static const struct nla_policy
-ip_set_setname2_policy[IPSET_ATTR_CMD_MAX + 1] = {
- [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 },
- [IPSET_ATTR_SETNAME] = { .type = NLA_NUL_STRING,
- .len = IPSET_MAXNAMELEN - 1 },
- [IPSET_ATTR_SETNAME2] = { .type = NLA_NUL_STRING,
- .len = IPSET_MAXNAMELEN - 1 },
-};
-
-static int
-ip_set_rename(struct sk_buff *skb, struct genl_info *info)
-{
- struct nlattr *const *attr = info->attrs;
- 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 ||
- attr[IPSET_ATTR_SETNAME2] == NULL))
- return -IPSET_ERR_PROTOCOL;
-
- set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
- if (set == NULL)
- return -ENOENT;
-
- 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)) {
- ret = -IPSET_ERR_EXIST_SETNAME2;
- goto out;
- }
- }
- strncpy(set->name, name2, IPSET_MAXNAMELEN);
-
-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.
- *
- * 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.
- */
-
-static int
-ip_set_swap(struct sk_buff *skb, struct genl_info *info)
-{
- struct nlattr *const *attr = info->attrs;
- struct ip_set *from, *to;
- ip_set_id_t from_id, to_id;
- char from_name[IPSET_MAXNAMELEN];
-
- if (unlikely(protocol_failed(attr) ||
- attr[IPSET_ATTR_SETNAME] == NULL ||
- attr[IPSET_ATTR_SETNAME2] == NULL))
- return -IPSET_ERR_PROTOCOL;
-
- from_id = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME]));
- if (from_id == IPSET_INVALID_ID)
- return -ENOENT;
-
- to_id = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME2]));
- if (to_id == IPSET_INVALID_ID)
- return -IPSET_ERR_EXIST_SETNAME2;
-
- from = ip_set_list[from_id];
- to = ip_set_list[to_id];
-
- /* Features must not change.
- * Not an artifical restriction anymore, as we must prevent
- * possible loops created by swapping in setlist type of sets. */
- if (!(from->type->features == to->type->features &&
- from->type->family == to->type->family))
- return -IPSET_ERR_TYPE_MISMATCH;
-
- strncpy(from_name, from->name, IPSET_MAXNAMELEN);
- strncpy(from->name, to->name, IPSET_MAXNAMELEN);
- strncpy(to->name, from_name, IPSET_MAXNAMELEN);
-
- 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;
-}
-
-/* List/save set data */
-
-#define DUMP_INIT 0
-#define DUMP_ALL 1
-#define DUMP_ONE 2
-#define DUMP_LAST 3
-
-#define DUMP_TYPE(arg) (((u32)(arg)) & 0x0000FFFF)
-#define DUMP_FLAGS(arg) (((u32)(arg)) >> 16)
-
-static int
-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_byindex((ip_set_id_t) cb->args[1]);
- }
- return 0;
-}
-
-static inline void
-dump_attrs(struct genlmsg_buf *phdr)
-{
- const struct nlattr *attr;
- const struct nlmsghdr *nlh =
- (const void *)phdr - GENL_HDRLEN - NLMSG_HDRLEN;
- int rem;
-
- pr_debug("dump nlmsg\n");
- nlmsg_for_each_attr(attr, nlh, sizeof(struct genlmsghdr), rem) {
- pr_debug("type: %u, len %u\n", nla_type(attr), attr->nla_len);
- }
-}
-
-static int
-dump_init(struct netlink_callback *cb)
-{
- struct nlmsghdr *nlh = nlmsg_hdr(cb->skb);
- int min_len = NLMSG_SPACE(sizeof(struct genlmsghdr));
- struct nlattr *cda[IPSET_ATTR_CMD_MAX+1];
- struct nlattr *attr = (void *)nlh + min_len;
- u32 dump_type;
- ip_set_id_t index;
-
- /* Second pass, so parser can't fail */
- nla_parse(cda, IPSET_ATTR_CMD_MAX,
- attr, nlh->nlmsg_len - min_len, ip_set_setname_policy);
-
- /* cb->args[0] : dump single set/all sets
- * [1] : set index
- * [..]: type specific
- */
-
- if (cda[IPSET_ATTR_SETNAME]) {
- index = find_set_id(nla_data(cda[IPSET_ATTR_SETNAME]));
- if (index == IPSET_INVALID_ID)
- return -ENOENT;
-
- dump_type = DUMP_ONE;
- cb->args[1] = index;
- } else
- dump_type = DUMP_ALL;
-
- if (cda[IPSET_ATTR_FLAGS]) {
- u32 f = ip_set_get_h32(cda[IPSET_ATTR_FLAGS]);
- dump_type |= (f << 16);
- }
- cb->args[0] = dump_type;
-
- return 0;
-}
-
-static int
-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 genlmsg_buf *nlh = NULL;
- unsigned int flags = NETLINK_CB(cb->skb).pid ? NLM_F_MULTI : 0;
- u32 dump_type, dump_flags;
- int ret = 0;
-
- if (!cb->args[0]) {
- ret = dump_init(cb);
- if (ret < 0) {
- struct nlmsghdr *nlh = nlmsg_hdr(cb->skb);
- /* We have to create and send the error message
- * manually :-( */
- if (nlh->nlmsg_flags & NLM_F_ACK)
- netlink_ack(cb->skb, nlh, ret);
- return ret;
- }
- }
-
- if (cb->args[1] >= ip_set_max)
- goto out;
-
- dump_type = DUMP_TYPE(cb->args[0]);
- dump_flags = DUMP_FLAGS(cb->args[0]);
- max = dump_type == DUMP_ONE ? cb->args[1] + 1 : ip_set_max;
-dump_last:
- pr_debug("args[0]: %u %u args[1]: %ld\n",
- dump_type, dump_flags, cb->args[1]);
- for (; cb->args[1] < max; cb->args[1]++) {
- index = (ip_set_id_t) cb->args[1];
- set = ip_set_list[index];
- if (set == NULL) {
- if (dump_type == DUMP_ONE) {
- ret = -ENOENT;
- goto out;
- }
- continue;
- }
- /* When dumping all sets, we must dump "sorted"
- * so that lists (unions of sets) are dumped last.
- */
- if (dump_type != DUMP_ONE &&
- ((dump_type == DUMP_ALL) ==
- !!(set->type->features & IPSET_DUMP_LAST)))
- continue;
- pr_debug("List set: %s\n", set->name);
- if (!cb->args[2]) {
- /* Start listing: make sure set won't be destroyed */
- pr_debug("reference set\n");
- __ip_set_get(index);
- }
- nlh = start_msg(skb, NETLINK_CB(cb->skb).pid,
- cb->nlh->nlmsg_seq, flags,
- IPSET_CMD_LIST);
- if (!nlh) {
- ret = -EMSGSIZE;
- goto release_refcount;
- }
- NLA_PUT_U8(skb, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL);
- NLA_PUT_STRING(skb, IPSET_ATTR_SETNAME, set->name);
- if (dump_flags & IPSET_FLAG_LIST_SETNAME)
- goto next_set;
- switch (cb->args[2]) {
- case 0:
- /* Core header data */
- NLA_PUT_STRING(skb, IPSET_ATTR_TYPENAME,
- set->type->name);
- NLA_PUT_U8(skb, IPSET_ATTR_FAMILY,
- set->family);
- NLA_PUT_U8(skb, IPSET_ATTR_REVISION,
- set->revision);
- ret = set->variant->head(set, skb);
- if (ret < 0)
- goto release_refcount;
- if (dump_flags & IPSET_FLAG_LIST_HEADER)
- goto next_set;
- /* Fall through and add elements */
- default:
- read_lock_bh(&set->lock);
- ret = set->variant->list(set, skb, cb);
- read_unlock_bh(&set->lock);
- if (!cb->args[2])
- /* Set is done, proceed with next one */
- goto next_set;
- goto release_refcount;
- }
- }
- /* If we dump all sets, continue with dumping last ones */
- if (dump_type == DUMP_ALL) {
- dump_type = DUMP_LAST;
- cb->args[0] = dump_type | (dump_flags << 16);
- cb->args[1] = 0;
- goto dump_last;
- }
- goto out;
-
-nla_put_failure:
- ret = -EFAULT;
-next_set:
- if (dump_type == DUMP_ONE)
- cb->args[1] = IPSET_INVALID_ID;
- else
- cb->args[1]++;
-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_byindex(index);
- cb->args[2] = 0;
- }
-out:
- if (nlh) {
- genlmsg_end(skb, nlh);
- pr_debug("nlmsg_len: %u\n", skb->len);
- dump_attrs(nlh);
- }
-
- return ret < 0 ? ret : skb->len;
-}
-
-static int
-ip_set_dump(struct sk_buff *skb, struct genl_info *info)
-{
- struct nlattr *const *attr = info->attrs;
- struct nlmsghdr *nlh = info->nlhdr;
- struct sock *ctnl = genl_info_net(info)->genl_sock;
- int ret;
-
- if (unlikely(protocol_failed(attr)))
- return -IPSET_ERR_PROTOCOL;
-
- genl_unlock();
- ret = netlink_dump_start(ctnl, skb, nlh,
- ip_set_dump_start,
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)
- ip_set_dump_done);
-#else
- ip_set_dump_done, 0);
-#endif
- genl_lock();
- return ret;
-}
-
-/* Add, del and test */
-
-static const struct nla_policy ip_set_adt_policy[IPSET_ATTR_CMD_MAX + 1] = {
- [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 },
- [IPSET_ATTR_SETNAME] = { .type = NLA_NUL_STRING,
- .len = IPSET_MAXNAMELEN - 1 },
- [IPSET_ATTR_LINENO] = { .type = NLA_U32 },
- [IPSET_ATTR_DATA] = { .type = NLA_NESTED },
- [IPSET_ATTR_ADT] = { .type = NLA_NESTED },
-};
-
-static int
-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)
-{
- int ret;
- u32 lineno = 0;
- bool eexist = flags & IPSET_FLAG_EXIST, retried = false;
-
- do {
- write_lock_bh(&set->lock);
- ret = set->variant->uadt(set, tb, adt, &lineno, flags, retried);
- write_unlock_bh(&set->lock);
- retried = true;
- } while (ret == -EAGAIN &&
- set->variant->resize &&
- (ret = set->variant->resize(set, retried)) == 0);
-
- if (!ret || (ret == -IPSET_ERR_EXIST && eexist))
- return 0;
- if (lineno && use_lineno) {
- /* Error in restore/batch mode: send back 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 genlmsghdr));
- 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;
-}
-
-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) ||
- attr[IPSET_ATTR_SETNAME] == NULL ||
- !((attr[IPSET_ATTR_DATA] != NULL) ^
- (attr[IPSET_ATTR_ADT] != NULL)) ||
- (attr[IPSET_ATTR_DATA] != NULL &&
- !flag_nested(attr[IPSET_ATTR_DATA])) ||
- (attr[IPSET_ATTR_ADT] != NULL &&
- (!flag_nested(attr[IPSET_ATTR_ADT]) ||
- attr[IPSET_ATTR_LINENO] == NULL))))
- return -IPSET_ERR_PROTOCOL;
-
- set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
- if (set == NULL)
- return -ENOENT;
-
- use_lineno = !!attr[IPSET_ATTR_LINENO];
- if (attr[IPSET_ATTR_DATA]) {
- 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) ||
- nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, nla,
- set->type->adt_policy))
- return -IPSET_ERR_PROTOCOL;
- ret = call_ad(ctnl, skb, set, tb, IPSET_ADD,
- flags, use_lineno);
- if (ret < 0)
- return ret;
- }
- }
- return ret;
-}
-
-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) ||
- attr[IPSET_ATTR_SETNAME] == NULL ||
- !((attr[IPSET_ATTR_DATA] != NULL) ^
- (attr[IPSET_ATTR_ADT] != NULL)) ||
- (attr[IPSET_ATTR_DATA] != NULL &&
- !flag_nested(attr[IPSET_ATTR_DATA])) ||
- (attr[IPSET_ATTR_ADT] != NULL &&
- (!flag_nested(attr[IPSET_ATTR_ADT]) ||
- attr[IPSET_ATTR_LINENO] == NULL))))
- return -IPSET_ERR_PROTOCOL;
-
- set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
- if (set == NULL)
- return -ENOENT;
-
- use_lineno = !!attr[IPSET_ATTR_LINENO];
- if (attr[IPSET_ATTR_DATA]) {
- 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) ||
- nla_parse_nested(tb, IPSET_ATTR_ADT_MAX, nla,
- set->type->adt_policy))
- return -IPSET_ERR_PROTOCOL;
- ret = call_ad(ctnl, skb, set, tb, IPSET_DEL,
- flags, use_lineno);
- if (ret < 0)
- return ret;
- }
- }
- return ret;
-}
-
-static int
-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) ||
- attr[IPSET_ATTR_SETNAME] == NULL ||
- attr[IPSET_ATTR_DATA] == NULL ||
- !flag_nested(attr[IPSET_ATTR_DATA])))
- return -IPSET_ERR_PROTOCOL;
-
- set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
- if (set == NULL)
- 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, tb, IPSET_TEST, NULL, 0, 0);
- read_unlock_bh(&set->lock);
- /* Userspace can't trigger element to be re-added */
- if (ret == -EAGAIN)
- ret = 1;
-
- return ret < 0 ? ret : ret > 0 ? 0 : -IPSET_ERR_EXIST;
-}
-
-/* Get headed data of a set */
-
-static int
-ip_set_header(struct sk_buff *skb, struct genl_info *info)
-{
- const struct ip_set *set;
- struct nlattr *const *attr = info->attrs;
- const struct nlmsghdr *nlh = info->nlhdr;
- struct sk_buff *skb2;
- struct genlmsg_buf *nlh2;
- ip_set_id_t index;
- int ret = 0;
-
- if (unlikely(protocol_failed(attr) ||
- attr[IPSET_ATTR_SETNAME] == NULL))
- return -IPSET_ERR_PROTOCOL;
-
- index = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME]));
- if (index == IPSET_INVALID_ID)
- return -ENOENT;
- set = ip_set_list[index];
-
- skb2 = genlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
- if (skb2 == NULL)
- return -ENOMEM;
-
- nlh2 = start_msg(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0,
- IPSET_CMD_HEADER);
- if (!nlh2)
- goto nlmsg_failure;
- NLA_PUT_U8(skb2, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL);
- NLA_PUT_STRING(skb2, IPSET_ATTR_SETNAME, set->name);
- NLA_PUT_STRING(skb2, IPSET_ATTR_TYPENAME, set->type->name);
- NLA_PUT_U8(skb2, IPSET_ATTR_FAMILY, set->family);
- NLA_PUT_U8(skb2, IPSET_ATTR_REVISION, set->revision);
- genlmsg_end(skb2, nlh2);
-
- ret = genlmsg_unicast(genl_info_net(info), skb2, NETLINK_CB(skb).pid);
- if (ret < 0)
- return ret;
-
- return 0;
-
-nla_put_failure:
- genlmsg_cancel(skb2, nlh2);
-nlmsg_failure:
- kfree_skb(skb2);
- return -EMSGSIZE;
-}
-
-/* Get type data */
-
-static const struct nla_policy ip_set_type_policy[IPSET_ATTR_CMD_MAX + 1] = {
- [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 },
- [IPSET_ATTR_TYPENAME] = { .type = NLA_NUL_STRING,
- .len = IPSET_MAXNAMELEN - 1 },
- [IPSET_ATTR_FAMILY] = { .type = NLA_U8 },
-};
-
-static int
-ip_set_type(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 genlmsg_buf *nlh2;
- u8 family, min, max;
- const char *typename;
- int ret = 0;
-
- if (unlikely(protocol_failed(attr) ||
- attr[IPSET_ATTR_TYPENAME] == NULL ||
- attr[IPSET_ATTR_FAMILY] == NULL))
- return -IPSET_ERR_PROTOCOL;
-
- family = nla_get_u8(attr[IPSET_ATTR_FAMILY]);
- typename = nla_data(attr[IPSET_ATTR_TYPENAME]);
- ret = find_set_type_minmax(typename, family, &min, &max);
- if (ret)
- return ret;
-
- skb2 = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
- if (skb2 == NULL)
- return -ENOMEM;
-
- nlh2 = start_msg(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0,
- IPSET_CMD_TYPE);
- if (!nlh2)
- goto nlmsg_failure;
- NLA_PUT_U8(skb2, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL);
- NLA_PUT_STRING(skb2, IPSET_ATTR_TYPENAME, typename);
- NLA_PUT_U8(skb2, IPSET_ATTR_FAMILY, family);
- NLA_PUT_U8(skb2, IPSET_ATTR_REVISION, max);
- NLA_PUT_U8(skb2, IPSET_ATTR_REVISION_MIN, min);
- genlmsg_end(skb2, nlh2);
-
- 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 ret;
-
- return 0;
-
-nla_put_failure:
- genlmsg_cancel(skb2, nlh2);
-nlmsg_failure:
- kfree_skb(skb2);
- return -EMSGSIZE;
-}
-
-/* Get protocol version */
-
-static const struct nla_policy
-ip_set_protocol_policy[IPSET_ATTR_CMD_MAX + 1] = {
- [IPSET_ATTR_PROTOCOL] = { .type = NLA_U8 },
-};
-
-static int
-ip_set_protocol(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 genlmsg_buf *nlh2;
- int ret = 0;
-
- if (unlikely(attr[IPSET_ATTR_PROTOCOL] == NULL))
- return -IPSET_ERR_PROTOCOL;
-
- skb2 = genlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
- if (skb2 == NULL)
- return -ENOMEM;
-
- nlh2 = start_msg(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0,
- IPSET_CMD_PROTOCOL);
- if (!nlh2)
- goto nlmsg_failure;
- NLA_PUT_U8(skb2, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL);
- genlmsg_end(skb2, nlh2);
-
- ret = genlmsg_unicast(genl_info_net(info), skb2, NETLINK_CB(skb).pid);
- if (ret < 0)
- return ret;
-
- return 0;
-
-nla_put_failure:
- genlmsg_cancel(skb2, nlh2);
-nlmsg_failure:
- kfree_skb(skb2);
- return -EMSGSIZE;
-}
-
-static struct genl_ops ip_set_netlink_subsys_cb[] __read_mostly = {
- {
- .cmd = IPSET_CMD_CREATE,
- .flags = GENL_ADMIN_PERM,
- .doit = ip_set_create,
- .policy = ip_set_create_policy,
- },
- {
- .cmd = IPSET_CMD_DESTROY,
- .flags = GENL_ADMIN_PERM,
- .doit = ip_set_destroy,
- .policy = ip_set_setname_policy,
- },
- {
- .cmd = IPSET_CMD_FLUSH,
- .flags = GENL_ADMIN_PERM,
- .doit = ip_set_flush,
- .policy = ip_set_setname_policy,
- },
- {
- .cmd = IPSET_CMD_RENAME,
- .flags = GENL_ADMIN_PERM,
- .doit = ip_set_rename,
- .policy = ip_set_setname2_policy,
- },
- {
- .cmd = IPSET_CMD_SWAP,
- .flags = GENL_ADMIN_PERM,
- .doit = ip_set_swap,
- .policy = ip_set_setname2_policy,
- },
- {
- .cmd = IPSET_CMD_LIST,
- .flags = GENL_ADMIN_PERM,
- .doit = ip_set_dump,
- .policy = ip_set_setname_policy,
- },
- {
- .cmd = IPSET_CMD_SAVE,
- .flags = GENL_ADMIN_PERM,
- .doit = ip_set_dump,
- .policy = ip_set_setname_policy,
- },
- {
- .cmd = IPSET_CMD_ADD,
- .flags = GENL_ADMIN_PERM,
- .doit = ip_set_uadd,
- .policy = ip_set_adt_policy,
- },
- {
- .cmd = IPSET_CMD_DEL,
- .flags = GENL_ADMIN_PERM,
- .doit = ip_set_udel,
- .policy = ip_set_adt_policy,
- },
- {
- .cmd = IPSET_CMD_TEST,
- .flags = GENL_ADMIN_PERM,
- .doit = ip_set_utest,
- .policy = ip_set_adt_policy,
- },
- {
- .cmd = IPSET_CMD_HEADER,
- .flags = GENL_ADMIN_PERM,
- .doit = ip_set_header,
- .policy = ip_set_setname_policy,
- },
- {
- .cmd = IPSET_CMD_TYPE,
- .flags = GENL_ADMIN_PERM,
- .doit = ip_set_type,
- .policy = ip_set_type_policy,
- },
- {
- .cmd = IPSET_CMD_PROTOCOL,
- .flags = GENL_ADMIN_PERM,
- .doit = ip_set_protocol,
- .policy = ip_set_protocol_policy,
- },
-};
-
-static struct genl_family ip_set_netlink_subsys __read_mostly = {
- .name = "ip_set",
- .id = GENL_ID_GENERATE,
- .hdrsize = 0,
- .version = 5,
- .maxattr = IPSET_ATTR_CMD_MAX,
-};
-
-/* Interface to iptables/ip6tables */
-
-static int
-ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len)
-{
- unsigned *op;
- void *data;
- int copylen = *len, ret = 0;
-
- if (!capable(CAP_NET_ADMIN))
- return -EPERM;
- if (optval != SO_IP_SET)
- return -EBADF;
- if (*len < sizeof(unsigned))
- return -EINVAL;
-
- data = vmalloc(*len);
- if (!data)
- return -ENOMEM;
- if (copy_from_user(data, user, *len) != 0) {
- ret = -EFAULT;
- goto done;
- }
- op = (unsigned *) data;
-
- if (*op < IP_SET_OP_VERSION) {
- /* Check the version at the beginning of operations */
- struct ip_set_req_version *req_version = data;
- if (req_version->version != IPSET_PROTOCOL) {
- ret = -EPROTO;
- goto done;
- }
- }
-
- switch (*op) {
- case IP_SET_OP_VERSION: {
- struct ip_set_req_version *req_version = data;
-
- if (*len != sizeof(struct ip_set_req_version)) {
- ret = -EINVAL;
- goto done;
- }
-
- req_version->version = IPSET_PROTOCOL;
- ret = copy_to_user(user, req_version,
- sizeof(struct ip_set_req_version));
- goto done;
- }
- case IP_SET_OP_GET_BYNAME: {
- struct ip_set_req_get_set *req_get = data;
-
- if (*len != sizeof(struct ip_set_req_get_set)) {
- ret = -EINVAL;
- goto done;
- }
- req_get->set.name[IPSET_MAXNAMELEN - 1] = '\0';
- genl_lock();
- req_get->set.index = find_set_id(req_get->set.name);
- genl_unlock();
- goto copy;
- }
- case IP_SET_OP_GET_BYINDEX: {
- struct ip_set_req_get_set *req_get = data;
-
- if (*len != sizeof(struct ip_set_req_get_set) ||
- req_get->set.index >= ip_set_max) {
- ret = -EINVAL;
- goto done;
- }
- genl_lock();
- strncpy(req_get->set.name,
- ip_set_list[req_get->set.index]
- ? ip_set_list[req_get->set.index]->name : "",
- IPSET_MAXNAMELEN);
- genl_unlock();
- goto copy;
- }
- default:
- ret = -EBADMSG;
- goto done;
- } /* end of switch(op) */
-
-copy:
- ret = copy_to_user(user, data, copylen);
-
-done:
- vfree(data);
- if (ret > 0)
- ret = 0;
- return ret;
-}
-
-static struct nf_sockopt_ops so_set __read_mostly = {
- .pf = PF_INET,
- .get_optmin = SO_IP_SET,
- .get_optmax = SO_IP_SET + 1,
- .get = &ip_set_sockfn_get,
- .owner = THIS_MODULE,
-};
-
-static int __init
-ip_set_init(void)
-{
- int ret;
-
- if (max_sets)
- ip_set_max = max_sets;
- if (ip_set_max >= IPSET_INVALID_ID)
- ip_set_max = IPSET_INVALID_ID - 1;
-
- ip_set_list = kzalloc(sizeof(struct ip_set *) * ip_set_max,
- GFP_KERNEL);
- if (!ip_set_list)
- return -ENOMEM;
-
- ret = genl_register_family_with_ops(&ip_set_netlink_subsys,
- ip_set_netlink_subsys_cb, ARRAY_SIZE(ip_set_netlink_subsys_cb));
- if (ret != 0) {
- pr_err("ip_set: cannot register with genetlink.");
- kfree(ip_set_list);
- return ret;
- }
- ret = nf_register_sockopt(&so_set);
- if (ret != 0) {
- pr_err("SO_SET registry failed: %d\n", ret);
- genl_unregister_family(&ip_set_netlink_subsys);
- kfree(ip_set_list);
- return ret;
- }
-
- pr_notice("ip_set: protocol %u\n", IPSET_PROTOCOL);
- return 0;
-}
-
-static void __exit
-ip_set_fini(void)
-{
- /* There can't be any existing set */
- nf_unregister_sockopt(&so_set);
- genl_unregister_family(&ip_set_netlink_subsys);
- kfree(ip_set_list);
- pr_debug("these are the famous last words\n");
-}
-
-module_init(ip_set_init);
-module_exit(ip_set_fini);
+++ /dev/null
-/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/* Get Layer-4 data from the packets */
-
-#include <linux/ip.h>
-#include <linux/skbuff.h>
-#include <linux/icmp.h>
-#include <linux/icmpv6.h>
-#include <linux/sctp.h>
-#include <linux/version.h>
-#include <linux/netfilter_ipv6/ip6_tables.h>
-#include <net/ip.h>
-#include <net/ipv6.h>
-
-#include "ip_set_getport.h"
-
-/* We must handle non-linear skbs */
-static bool
-get_port(const struct sk_buff *skb, int protocol, unsigned int protooff,
- bool src, __be16 *port, u8 *proto)
-{
- switch (protocol) {
- case IPPROTO_TCP: {
- struct tcphdr _tcph;
- const struct tcphdr *th;
-
- th = skb_header_pointer(skb, protooff, sizeof(_tcph), &_tcph);
- if (th == NULL)
- /* No choice either */
- return false;
-
- *port = src ? th->source : th->dest;
- break;
- }
- 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;
-
- uh = skb_header_pointer(skb, protooff, sizeof(_udph), &_udph);
- if (uh == NULL)
- /* No choice either */
- return false;
-
- *port = src ? uh->source : uh->dest;
- break;
- }
- case IPPROTO_ICMP: {
- struct icmphdr _ich;
- const struct icmphdr *ic;
-
- ic = skb_header_pointer(skb, protooff, sizeof(_ich), &_ich);
- if (ic == NULL)
- return false;
-
- *port = (__force __be16)htons((ic->type << 8) | ic->code);
- break;
- }
- case IPPROTO_ICMPV6: {
- struct icmp6hdr _ich;
- const struct icmp6hdr *ic;
-
- ic = skb_header_pointer(skb, protooff, sizeof(_ich), &_ich);
- if (ic == NULL)
- return false;
-
- *port = (__force __be16)
- htons((ic->icmp6_type << 8) | ic->icmp6_code);
- break;
- }
- default:
- break;
- }
- *proto = protocol;
-
- return true;
-}
-
-bool
-ip_set_get_ip4_port(const struct sk_buff *skb, bool src,
- __be16 *port, u8 *proto)
-{
- const struct iphdr *iph = ip_hdr(skb);
- unsigned int protooff = ip_hdrlen(skb);
- int protocol = iph->protocol;
-
- /* See comments at tcp_match in ip_tables.c */
- if (protocol <= 0 || (ntohs(iph->frag_off) & IP_OFFSET))
- return false;
-
- return get_port(skb, protocol, protooff, src, port, proto);
-}
-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)
-{
- int protoff;
- u8 nexthdr;
- __be16 frag_off;
-
- nexthdr = ipv6_hdr(skb)->nexthdr;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)
- protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr);
-#else
- protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr, &frag_off);
-#endif
- if (protoff < 0)
- return false;
-
- 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)
-{
- bool ret;
- u8 proto;
-
- switch (pf) {
- case NFPROTO_IPV4:
- ret = ip_set_get_ip4_port(skb, src, port, &proto);
- break;
- case NFPROTO_IPV6:
- ret = ip_set_get_ip6_port(skb, src, port, &proto);
- break;
- default:
- return false;
- }
- if (!ret)
- return ret;
- switch (proto) {
- case IPPROTO_TCP:
- case IPPROTO_UDP:
- return true;
- default:
- return false;
- }
-}
-EXPORT_SYMBOL_GPL(ip_set_get_ip_port);
+++ /dev/null
-#ifndef _IP_SET_GETPORT_H
-#define _IP_SET_GETPORT_H
-
-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);
-
-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*/
+++ /dev/null
-#ifndef __IP_SET_HASH_H
-#define __IP_SET_HASH_H
-
-/* Hash type specific error codes */
-enum {
- /* Hash is full */
- IPSET_ERR_HASH_FULL = IPSET_ERR_TYPE_SPECIFIC,
- /* Null-valued element */
- IPSET_ERR_HASH_ELEM,
- /* Invalid protocol */
- IPSET_ERR_INVALID_PROTO,
- /* Protocol missing but must be specified */
- IPSET_ERR_MISSING_PROTO,
- /* Range not supported */
- IPSET_ERR_HASH_RANGE_UNSUPPORTED,
- /* Invalid range */
- IPSET_ERR_HASH_RANGE,
-};
-
-#ifdef __KERNEL__
-
-#define IPSET_DEFAULT_HASHSIZE 1024
-#define IPSET_MIMINAL_HASHSIZE 64
-#define IPSET_DEFAULT_MAXELEM 65536
-#define IPSET_DEFAULT_PROBES 4
-#define IPSET_DEFAULT_RESIZE 100
-
-#endif /* __KERNEL__ */
-
-#endif /* __IP_SET_HASH_H */
+++ /dev/null
-/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/* Kernel module implementing an IP set type: the hash:ip type */
-
-#include "jhash.h"
-#include <linux/module.h>
-#include <linux/ip.h>
-#include <linux/skbuff.h>
-#include <linux/errno.h>
-#include <linux/random.h>
-#include <net/ip.h>
-#include <net/ipv6.h>
-#include <net/netlink.h>
-#include <net/tcp.h>
-
-#include <linux/netfilter.h>
-#include "pfxlen.h"
-#include "ip_set.h"
-#include "ip_set_timeout.h"
-#include "ip_set_hash.h"
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
-MODULE_DESCRIPTION("hash:ip type of IP sets");
-MODULE_ALIAS("ip_set_hash:ip");
-
-/* Type specific function prefix */
-#define TYPE hash_ip
-
-static bool
-hash_ip_same_set(const struct ip_set *a, const struct ip_set *b);
-
-#define hash_ip4_same_set hash_ip_same_set
-#define hash_ip6_same_set hash_ip_same_set
-
-/* The type variant functions: IPv4 */
-
-/* Member elements without timeout */
-struct hash_ip4_elem {
- __be32 ip;
-};
-
-/* Member elements with timeout support */
-struct hash_ip4_telem {
- __be32 ip;
- unsigned long timeout;
-};
-
-static inline bool
-hash_ip4_data_equal(const struct hash_ip4_elem *ip1,
- const struct hash_ip4_elem *ip2,
- u32 *multi)
-{
- return ip1->ip == ip2->ip;
-}
-
-static inline bool
-hash_ip4_data_isnull(const struct hash_ip4_elem *elem)
-{
- return elem->ip == 0;
-}
-
-static inline void
-hash_ip4_data_copy(struct hash_ip4_elem *dst, const struct hash_ip4_elem *src)
-{
- dst->ip = src->ip;
-}
-
-/* Zero valued IP addresses cannot be stored */
-static inline void
-hash_ip4_data_zero_out(struct hash_ip4_elem *elem)
-{
- elem->ip = 0;
-}
-
-static inline bool
-hash_ip4_data_list(struct sk_buff *skb, const struct hash_ip4_elem *data)
-{
- NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
- return 0;
-
-nla_put_failure:
- return 1;
-}
-
-static bool
-hash_ip4_data_tlist(struct sk_buff *skb, const struct hash_ip4_elem *data)
-{
- const struct hash_ip4_telem *tdata =
- (const struct hash_ip4_telem *)data;
-
- NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
- NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
- htonl(ip_set_timeout_get(tdata->timeout)));
-
- return 0;
-
-nla_put_failure:
- return 1;
-}
-
-#define IP_SET_HASH_WITH_NETMASK
-#define PF 4
-#define HOST_MASK 32
-#include "ip_set_ahash.h"
-
-static inline void
-hash_ip4_data_next(struct ip_set_hash *h, const struct hash_ip4_elem *d)
-{
- h->next.ip = ntohl(d->ip);
-}
-
-static int
-hash_ip4_kadt(struct ip_set *set, const struct sk_buff *skb,
- const struct xt_action_param *par,
- enum ipset_adt adt, const struct ip_set_adt_opt *opt)
-{
- const struct ip_set_hash *h = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- __be32 ip;
-
- ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &ip);
- ip &= ip_set_netmask(h->netmask);
- if (ip == 0)
- return -EINVAL;
-
- return adtfn(set, &ip, opt_timeout(opt, h), opt->cmdflags);
-}
-
-static int
-hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
-{
- const struct ip_set_hash *h = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- u32 ip, ip_to, hosts, timeout = h->timeout;
- __be32 nip;
- int ret = 0;
-
- 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;
-
- ip &= ip_set_hostmask(h->netmask);
-
- if (tb[IPSET_ATTR_TIMEOUT]) {
- if (!with_timeout(h->timeout))
- return -IPSET_ERR_TIMEOUT;
- timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
- }
-
- if (adt == IPSET_TEST) {
- nip = htonl(ip);
- if (nip == 0)
- return -IPSET_ERR_HASH_ELEM;
- return adtfn(set, &nip, timeout, flags);
- }
-
- 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);
- } else if (tb[IPSET_ATTR_CIDR]) {
- u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
-
- if (cidr > 32)
- return -IPSET_ERR_INVALID_CIDR;
- ip_set_mask_from_to(ip, ip_to, cidr);
- } else
- ip_to = ip;
-
- hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1);
-
- if (retried)
- ip = h->next.ip;
- for (; !before(ip_to, ip); ip += hosts) {
- nip = htonl(ip);
- if (nip == 0)
- return -IPSET_ERR_HASH_ELEM;
- ret = adtfn(set, &nip, timeout, flags);
-
- if (ret && !ip_set_eexist(ret, flags))
- return ret;
- else
- ret = 0;
- }
- return ret;
-}
-
-static bool
-hash_ip_same_set(const struct ip_set *a, const struct ip_set *b)
-{
- const struct ip_set_hash *x = a->data;
- const struct ip_set_hash *y = b->data;
-
- /* Resizing changes htable_bits, so we ignore it */
- return x->maxelem == y->maxelem &&
- x->timeout == y->timeout &&
- x->netmask == y->netmask;
-}
-
-/* The type variant functions: IPv6 */
-
-struct hash_ip6_elem {
- union nf_inet_addr ip;
-};
-
-struct hash_ip6_telem {
- union nf_inet_addr ip;
- unsigned long timeout;
-};
-
-static inline bool
-hash_ip6_data_equal(const struct hash_ip6_elem *ip1,
- const struct hash_ip6_elem *ip2,
- u32 *multi)
-{
- return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0;
-}
-
-static inline bool
-hash_ip6_data_isnull(const struct hash_ip6_elem *elem)
-{
- return ipv6_addr_any(&elem->ip.in6);
-}
-
-static inline void
-hash_ip6_data_copy(struct hash_ip6_elem *dst, const struct hash_ip6_elem *src)
-{
- dst->ip.in6 = src->ip.in6;
-}
-
-static inline void
-hash_ip6_data_zero_out(struct hash_ip6_elem *elem)
-{
- ipv6_addr_set(&elem->ip.in6, 0, 0, 0, 0);
-}
-
-static inline void
-ip6_netmask(union nf_inet_addr *ip, u8 prefix)
-{
- ip->ip6[0] &= ip_set_netmask6(prefix)[0];
- ip->ip6[1] &= ip_set_netmask6(prefix)[1];
- ip->ip6[2] &= ip_set_netmask6(prefix)[2];
- ip->ip6[3] &= ip_set_netmask6(prefix)[3];
-}
-
-static bool
-hash_ip6_data_list(struct sk_buff *skb, const struct hash_ip6_elem *data)
-{
- NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
- return 0;
-
-nla_put_failure:
- return 1;
-}
-
-static bool
-hash_ip6_data_tlist(struct sk_buff *skb, const struct hash_ip6_elem *data)
-{
- const struct hash_ip6_telem *e =
- (const struct hash_ip6_telem *)data;
-
- NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
- NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
- htonl(ip_set_timeout_get(e->timeout)));
- return 0;
-
-nla_put_failure:
- return 1;
-}
-
-#undef PF
-#undef HOST_MASK
-
-#define PF 6
-#define HOST_MASK 128
-#include "ip_set_ahash.h"
-
-static inline void
-hash_ip6_data_next(struct ip_set_hash *h, const struct hash_ip6_elem *d)
-{
-}
-
-static int
-hash_ip6_kadt(struct ip_set *set, const struct sk_buff *skb,
- const struct xt_action_param *par,
- enum ipset_adt adt, const struct ip_set_adt_opt *opt)
-{
- const struct ip_set_hash *h = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- union nf_inet_addr ip;
-
- ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &ip.in6);
- ip6_netmask(&ip, h->netmask);
- if (ipv6_addr_any(&ip.in6))
- return -EINVAL;
-
- return adtfn(set, &ip, opt_timeout(opt, h), opt->cmdflags);
-}
-
-static const struct nla_policy hash_ip6_adt_policy[IPSET_ATTR_ADT_MAX + 1] = {
- [IPSET_ATTR_IP] = { .type = NLA_NESTED },
- [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
- [IPSET_ATTR_LINENO] = { .type = NLA_U32 },
-};
-
-static int
-hash_ip6_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
-{
- const struct ip_set_hash *h = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- union nf_inet_addr ip;
- u32 timeout = h->timeout;
- int ret;
-
- if (unlikely(!tb[IPSET_ATTR_IP] ||
- !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])
- *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
-
- ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &ip);
- if (ret)
- return ret;
-
- ip6_netmask(&ip, h->netmask);
- if (ipv6_addr_any(&ip.in6))
- return -IPSET_ERR_HASH_ELEM;
-
- if (tb[IPSET_ATTR_TIMEOUT]) {
- if (!with_timeout(h->timeout))
- return -IPSET_ERR_TIMEOUT;
- timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
- }
-
- ret = adtfn(set, &ip, timeout, flags);
-
- return ip_set_eexist(ret, flags) ? 0 : ret;
-}
-
-/* Create hash:ip type of sets */
-
-static int
-hash_ip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
-{
- u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
- u8 netmask, hbits;
- struct ip_set_hash *h;
-
- if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
- return -IPSET_ERR_INVALID_FAMILY;
- netmask = set->family == NFPROTO_IPV4 ? 32 : 128;
- pr_debug("Create set %s with family %s\n",
- set->name, set->family == NFPROTO_IPV4 ? "inet" : "inet6");
-
- 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)))
- return -IPSET_ERR_PROTOCOL;
-
- if (tb[IPSET_ATTR_HASHSIZE]) {
- hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
- if (hashsize < IPSET_MIMINAL_HASHSIZE)
- hashsize = IPSET_MIMINAL_HASHSIZE;
- }
-
- if (tb[IPSET_ATTR_MAXELEM])
- maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
-
- if (tb[IPSET_ATTR_NETMASK]) {
- netmask = nla_get_u8(tb[IPSET_ATTR_NETMASK]);
-
- if ((set->family == NFPROTO_IPV4 && netmask > 32) ||
- (set->family == NFPROTO_IPV6 && netmask > 128) ||
- netmask == 0)
- return -IPSET_ERR_INVALID_NETMASK;
- }
-
- h = kzalloc(sizeof(*h), GFP_KERNEL);
- if (!h)
- return -ENOMEM;
-
- h->maxelem = maxelem;
- h->netmask = netmask;
- get_random_bytes(&h->initval, sizeof(h->initval));
- h->timeout = IPSET_NO_TIMEOUT;
-
- hbits = htable_bits(hashsize);
- h->table = ip_set_alloc(
- sizeof(struct htable)
- + jhash_size(hbits) * sizeof(struct hbucket));
- if (!h->table) {
- kfree(h);
- return -ENOMEM;
- }
- h->table->htable_bits = hbits;
-
- set->data = h;
-
- if (tb[IPSET_ATTR_TIMEOUT]) {
- h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
-
- set->variant = set->family == NFPROTO_IPV4
- ? &hash_ip4_tvariant : &hash_ip6_tvariant;
-
- if (set->family == NFPROTO_IPV4)
- hash_ip4_gc_init(set);
- else
- hash_ip6_gc_init(set);
- } else {
- set->variant = set->family == NFPROTO_IPV4
- ? &hash_ip4_variant : &hash_ip6_variant;
- }
-
- pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
- set->name, jhash_size(h->table->htable_bits),
- h->table->htable_bits, h->maxelem, set->data, h->table);
-
- return 0;
-}
-
-static struct ip_set_type hash_ip_type __read_mostly = {
- .name = "hash:ip",
- .protocol = IPSET_PROTOCOL,
- .features = IPSET_TYPE_IP,
- .dimension = IPSET_DIM_ONE,
- .family = NFPROTO_UNSPEC,
- .revision_min = 0,
- .revision_max = 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,
-};
-
-static int __init
-hash_ip_init(void)
-{
- return ip_set_type_register(&hash_ip_type);
-}
-
-static void __exit
-hash_ip_fini(void)
-{
- ip_set_type_unregister(&hash_ip_type);
-}
-
-module_init(hash_ip_init);
-module_exit(hash_ip_fini);
+++ /dev/null
-/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/* Kernel module implementing an IP set type: the hash:ip,port type */
-
-#include "jhash.h"
-#include <linux/module.h>
-#include <linux/ip.h>
-#include <linux/skbuff.h>
-#include <linux/errno.h>
-#include <linux/random.h>
-#include <net/ip.h>
-#include <net/ipv6.h>
-#include <net/netlink.h>
-#include <net/tcp.h>
-
-#include <linux/netfilter.h>
-#include "pfxlen.h"
-#include "ip_set.h"
-#include "ip_set_timeout.h"
-#include "ip_set_getport.h"
-#include "ip_set_hash.h"
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
-MODULE_DESCRIPTION("hash:ip,port type of IP sets");
-MODULE_ALIAS("ip_set_hash:ip,port");
-
-/* Type specific function prefix */
-#define TYPE hash_ipport
-
-static bool
-hash_ipport_same_set(const struct ip_set *a, const struct ip_set *b);
-
-#define hash_ipport4_same_set hash_ipport_same_set
-#define hash_ipport6_same_set hash_ipport_same_set
-
-/* The type variant functions: IPv4 */
-
-/* Member elements without timeout */
-struct hash_ipport4_elem {
- __be32 ip;
- __be16 port;
- u8 proto;
- u8 padding;
-};
-
-/* Member elements with timeout support */
-struct hash_ipport4_telem {
- __be32 ip;
- __be16 port;
- u8 proto;
- u8 padding;
- unsigned long timeout;
-};
-
-static inline bool
-hash_ipport4_data_equal(const struct hash_ipport4_elem *ip1,
- const struct hash_ipport4_elem *ip2,
- u32 *multi)
-{
- return ip1->ip == ip2->ip &&
- ip1->port == ip2->port &&
- ip1->proto == ip2->proto;
-}
-
-static inline bool
-hash_ipport4_data_isnull(const struct hash_ipport4_elem *elem)
-{
- return elem->proto == 0;
-}
-
-static inline void
-hash_ipport4_data_copy(struct hash_ipport4_elem *dst,
- const struct hash_ipport4_elem *src)
-{
- dst->ip = src->ip;
- dst->port = src->port;
- dst->proto = src->proto;
-}
-
-static inline void
-hash_ipport4_data_zero_out(struct hash_ipport4_elem *elem)
-{
- elem->proto = 0;
-}
-
-static bool
-hash_ipport4_data_list(struct sk_buff *skb,
- const struct hash_ipport4_elem *data)
-{
- NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
- NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
- NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
- return 0;
-
-nla_put_failure:
- return 1;
-}
-
-static bool
-hash_ipport4_data_tlist(struct sk_buff *skb,
- const struct hash_ipport4_elem *data)
-{
- const struct hash_ipport4_telem *tdata =
- (const struct hash_ipport4_telem *)data;
-
- NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
- NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port);
- NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
- NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
- htonl(ip_set_timeout_get(tdata->timeout)));
-
- return 0;
-
-nla_put_failure:
- return 1;
-}
-
-#define PF 4
-#define HOST_MASK 32
-#include "ip_set_ahash.h"
-
-static inline void
-hash_ipport4_data_next(struct ip_set_hash *h,
- const struct hash_ipport4_elem *d)
-{
- h->next.ip = ntohl(d->ip);
- h->next.port = ntohs(d->port);
-}
-
-static int
-hash_ipport4_kadt(struct ip_set *set, const struct sk_buff *skb,
- const struct xt_action_param *par,
- enum ipset_adt adt, const struct ip_set_adt_opt *opt)
-{
- const struct ip_set_hash *h = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- struct hash_ipport4_elem data = { };
-
- if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
- &data.port, &data.proto))
- return -EINVAL;
-
- ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
-
- return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
-}
-
-static int
-hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
-{
- const struct ip_set_hash *h = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- struct hash_ipport4_elem data = { };
- u32 ip, ip_to = 0, p = 0, port, port_to;
- u32 timeout = h->timeout;
- bool with_ports = false;
- int ret;
-
- 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)))
- return -IPSET_ERR_PROTOCOL;
-
- if (tb[IPSET_ATTR_LINENO])
- *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
-
- ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
- if (ret)
- return ret;
-
- if (tb[IPSET_ATTR_PORT])
- data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
- else
- return -IPSET_ERR_PROTOCOL;
-
- 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;
-
- if (!(with_ports || data.proto == IPPROTO_ICMP))
- data.port = 0;
-
- if (tb[IPSET_ATTR_TIMEOUT]) {
- if (!with_timeout(h->timeout))
- return -IPSET_ERR_TIMEOUT;
- timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
- }
-
- if (adt == IPSET_TEST ||
- !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
- tb[IPSET_ATTR_PORT_TO])) {
- ret = adtfn(set, &data, timeout, flags);
- return ip_set_eexist(ret, flags) ? 0 : ret;
- }
-
- ip = ntohl(data.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);
- } else if (tb[IPSET_ATTR_CIDR]) {
- u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
-
- if (cidr > 32)
- return -IPSET_ERR_INVALID_CIDR;
- ip_set_mask_from_to(ip, ip_to, cidr);
- } else
- ip_to = ip;
-
- 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);
- }
-
- if (retried)
- ip = h->next.ip;
- for (; !before(ip_to, ip); ip++) {
- p = retried && ip == h->next.ip ? h->next.port : port;
- for (; p <= port_to; p++) {
- data.ip = htonl(ip);
- data.port = htons(p);
- ret = adtfn(set, &data, timeout, flags);
-
- if (ret && !ip_set_eexist(ret, flags))
- return ret;
- else
- ret = 0;
- }
- }
- return ret;
-}
-
-static bool
-hash_ipport_same_set(const struct ip_set *a, const struct ip_set *b)
-{
- const struct ip_set_hash *x = a->data;
- const struct ip_set_hash *y = b->data;
-
- /* Resizing changes htable_bits, so we ignore it */
- return x->maxelem == y->maxelem &&
- x->timeout == y->timeout;
-}
-
-/* The type variant functions: IPv6 */
-
-struct hash_ipport6_elem {
- union nf_inet_addr ip;
- __be16 port;
- u8 proto;
- u8 padding;
-};
-
-struct hash_ipport6_telem {
- union nf_inet_addr ip;
- __be16 port;
- u8 proto;
- u8 padding;
- unsigned long timeout;
-};
-
-static inline bool
-hash_ipport6_data_equal(const struct hash_ipport6_elem *ip1,
- const struct hash_ipport6_elem *ip2,
- u32 *multi)
-{
- return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
- ip1->port == ip2->port &&
- ip1->proto == ip2->proto;
-}
-
-static inline bool
-hash_ipport6_data_isnull(const struct hash_ipport6_elem *elem)
-{
- return elem->proto == 0;
-}
-
-static inline void
-hash_ipport6_data_copy(struct hash_ipport6_elem *dst,
- const struct hash_ipport6_elem *src)
-{
- memcpy(dst, src, sizeof(*dst));
-}
-
-static inline void
-hash_ipport6_data_zero_out(struct hash_ipport6_elem *elem)
-{
- elem->proto = 0;
-}
-
-static bool
-hash_ipport6_data_list(struct sk_buff *skb,
- const struct hash_ipport6_elem *data)
-{
- NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
- NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
- NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
- return 0;
-
-nla_put_failure:
- return 1;
-}
-
-static bool
-hash_ipport6_data_tlist(struct sk_buff *skb,
- const struct hash_ipport6_elem *data)
-{
- const struct hash_ipport6_telem *e =
- (const struct hash_ipport6_telem *)data;
-
- NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
- NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
- NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
- NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
- htonl(ip_set_timeout_get(e->timeout)));
- return 0;
-
-nla_put_failure:
- return 1;
-}
-
-#undef PF
-#undef HOST_MASK
-
-#define PF 6
-#define HOST_MASK 128
-#include "ip_set_ahash.h"
-
-static inline void
-hash_ipport6_data_next(struct ip_set_hash *h,
- const struct hash_ipport6_elem *d)
-{
- h->next.port = ntohs(d->port);
-}
-
-static int
-hash_ipport6_kadt(struct ip_set *set, const struct sk_buff *skb,
- const struct xt_action_param *par,
- enum ipset_adt adt, const struct ip_set_adt_opt *opt)
-{
- const struct ip_set_hash *h = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- struct hash_ipport6_elem data = { };
-
- if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
- &data.port, &data.proto))
- return -EINVAL;
-
- ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
-
- return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
-}
-
-static int
-hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
-{
- const struct ip_set_hash *h = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- 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] ||
- !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) ||
- tb[IPSET_ATTR_IP_TO] ||
- tb[IPSET_ATTR_CIDR]))
- return -IPSET_ERR_PROTOCOL;
-
- if (tb[IPSET_ATTR_LINENO])
- *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
-
- ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
- if (ret)
- return ret;
-
- if (tb[IPSET_ATTR_PORT])
- data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
- else
- return -IPSET_ERR_PROTOCOL;
-
- 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;
-
- if (!(with_ports || data.proto == IPPROTO_ICMPV6))
- data.port = 0;
-
- if (tb[IPSET_ATTR_TIMEOUT]) {
- if (!with_timeout(h->timeout))
- return -IPSET_ERR_TIMEOUT;
- timeout = ip_set_timeout_uget(tb[IPSET_ATTR_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;
- }
-
- port = ntohs(data.port);
- port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
- if (port > port_to)
- swap(port, port_to);
-
- if (retried)
- port = h->next.port;
- for (; port <= port_to; port++) {
- data.port = htons(port);
- ret = adtfn(set, &data, timeout, flags);
-
- if (ret && !ip_set_eexist(ret, flags))
- return ret;
- else
- ret = 0;
- }
- return ret;
-}
-
-/* Create hash:ip type of sets */
-
-static int
-hash_ipport_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
-{
- struct ip_set_hash *h;
- u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
- u8 hbits;
-
- if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
- return -IPSET_ERR_INVALID_FAMILY;
-
- 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)))
- return -IPSET_ERR_PROTOCOL;
-
- if (tb[IPSET_ATTR_HASHSIZE]) {
- hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
- if (hashsize < IPSET_MIMINAL_HASHSIZE)
- hashsize = IPSET_MIMINAL_HASHSIZE;
- }
-
- if (tb[IPSET_ATTR_MAXELEM])
- maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
-
- h = kzalloc(sizeof(*h), GFP_KERNEL);
- if (!h)
- return -ENOMEM;
-
- h->maxelem = maxelem;
- get_random_bytes(&h->initval, sizeof(h->initval));
- h->timeout = IPSET_NO_TIMEOUT;
-
- hbits = htable_bits(hashsize);
- h->table = ip_set_alloc(
- sizeof(struct htable)
- + jhash_size(hbits) * sizeof(struct hbucket));
- if (!h->table) {
- kfree(h);
- return -ENOMEM;
- }
- h->table->htable_bits = hbits;
-
- set->data = h;
-
- if (tb[IPSET_ATTR_TIMEOUT]) {
- h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
-
- set->variant = set->family == NFPROTO_IPV4
- ? &hash_ipport4_tvariant : &hash_ipport6_tvariant;
-
- if (set->family == NFPROTO_IPV4)
- hash_ipport4_gc_init(set);
- else
- hash_ipport6_gc_init(set);
- } else {
- set->variant = set->family == NFPROTO_IPV4
- ? &hash_ipport4_variant : &hash_ipport6_variant;
- }
-
- pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
- set->name, jhash_size(h->table->htable_bits),
- h->table->htable_bits, h->maxelem, set->data, h->table);
-
- return 0;
-}
-
-static struct ip_set_type hash_ipport_type __read_mostly = {
- .name = "hash:ip,port",
- .protocol = IPSET_PROTOCOL,
- .features = IPSET_TYPE_IP | IPSET_TYPE_PORT,
- .dimension = IPSET_DIM_TWO,
- .family = NFPROTO_UNSPEC,
- .revision_min = 0,
- .revision_max = 1, /* SCTP and UDPLITE support added */
- .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,
-};
-
-static int __init
-hash_ipport_init(void)
-{
- return ip_set_type_register(&hash_ipport_type);
-}
-
-static void __exit
-hash_ipport_fini(void)
-{
- ip_set_type_unregister(&hash_ipport_type);
-}
-
-module_init(hash_ipport_init);
-module_exit(hash_ipport_fini);
+++ /dev/null
-/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/* Kernel module implementing an IP set type: the hash:ip,port,ip type */
-
-#include "jhash.h"
-#include <linux/module.h>
-#include <linux/ip.h>
-#include <linux/skbuff.h>
-#include <linux/errno.h>
-#include <linux/random.h>
-#include <net/ip.h>
-#include <net/ipv6.h>
-#include <net/netlink.h>
-#include <net/tcp.h>
-
-#include <linux/netfilter.h>
-#include "pfxlen.h"
-#include "ip_set.h"
-#include "ip_set_timeout.h"
-#include "ip_set_getport.h"
-#include "ip_set_hash.h"
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
-MODULE_DESCRIPTION("hash:ip,port,ip type of IP sets");
-MODULE_ALIAS("ip_set_hash:ip,port,ip");
-
-/* Type specific function prefix */
-#define TYPE hash_ipportip
-
-static bool
-hash_ipportip_same_set(const struct ip_set *a, const struct ip_set *b);
-
-#define hash_ipportip4_same_set hash_ipportip_same_set
-#define hash_ipportip6_same_set hash_ipportip_same_set
-
-/* The type variant functions: IPv4 */
-
-/* Member elements without timeout */
-struct hash_ipportip4_elem {
- __be32 ip;
- __be32 ip2;
- __be16 port;
- u8 proto;
- u8 padding;
-};
-
-/* Member elements with timeout support */
-struct hash_ipportip4_telem {
- __be32 ip;
- __be32 ip2;
- __be16 port;
- u8 proto;
- u8 padding;
- unsigned long timeout;
-};
-
-static inline bool
-hash_ipportip4_data_equal(const struct hash_ipportip4_elem *ip1,
- const struct hash_ipportip4_elem *ip2,
- u32 *multi)
-{
- return ip1->ip == ip2->ip &&
- ip1->ip2 == ip2->ip2 &&
- ip1->port == ip2->port &&
- ip1->proto == ip2->proto;
-}
-
-static inline bool
-hash_ipportip4_data_isnull(const struct hash_ipportip4_elem *elem)
-{
- return elem->proto == 0;
-}
-
-static inline void
-hash_ipportip4_data_copy(struct hash_ipportip4_elem *dst,
- const struct hash_ipportip4_elem *src)
-{
- memcpy(dst, src, sizeof(*dst));
-}
-
-static inline void
-hash_ipportip4_data_zero_out(struct hash_ipportip4_elem *elem)
-{
- elem->proto = 0;
-}
-
-static bool
-hash_ipportip4_data_list(struct sk_buff *skb,
- const struct hash_ipportip4_elem *data)
-{
- NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
- NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, data->ip2);
- NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
- NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
- return 0;
-
-nla_put_failure:
- return 1;
-}
-
-static bool
-hash_ipportip4_data_tlist(struct sk_buff *skb,
- const struct hash_ipportip4_elem *data)
-{
- const struct hash_ipportip4_telem *tdata =
- (const struct hash_ipportip4_telem *)data;
-
- NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
- NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, tdata->ip2);
- NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port);
- NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
- NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
- htonl(ip_set_timeout_get(tdata->timeout)));
-
- return 0;
-
-nla_put_failure:
- return 1;
-}
-
-#define PF 4
-#define HOST_MASK 32
-#include "ip_set_ahash.h"
-
-static inline void
-hash_ipportip4_data_next(struct ip_set_hash *h,
- const struct hash_ipportip4_elem *d)
-{
- h->next.ip = ntohl(d->ip);
- h->next.port = ntohs(d->port);
-}
-
-static int
-hash_ipportip4_kadt(struct ip_set *set, const struct sk_buff *skb,
- const struct xt_action_param *par,
- enum ipset_adt adt, const struct ip_set_adt_opt *opt)
-{
- const struct ip_set_hash *h = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- struct hash_ipportip4_elem data = { };
-
- if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
- &data.port, &data.proto))
- return -EINVAL;
-
- ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
- ip4addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &data.ip2);
-
- return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
-}
-
-static int
-hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
-{
- const struct ip_set_hash *h = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- struct hash_ipportip4_elem data = { };
- u32 ip, ip_to = 0, p = 0, port, port_to;
- u32 timeout = h->timeout;
- bool with_ports = false;
- int ret;
-
- 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)))
- return -IPSET_ERR_PROTOCOL;
-
- if (tb[IPSET_ATTR_LINENO])
- *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
-
- ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &data.ip);
- if (ret)
- return ret;
-
- ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP2], &data.ip2);
- if (ret)
- return ret;
-
- if (tb[IPSET_ATTR_PORT])
- data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
- else
- return -IPSET_ERR_PROTOCOL;
-
- 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;
-
- if (!(with_ports || data.proto == IPPROTO_ICMP))
- data.port = 0;
-
- if (tb[IPSET_ATTR_TIMEOUT]) {
- if (!with_timeout(h->timeout))
- return -IPSET_ERR_TIMEOUT;
- timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
- }
-
- if (adt == IPSET_TEST ||
- !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR] ||
- tb[IPSET_ATTR_PORT_TO])) {
- ret = adtfn(set, &data, timeout, flags);
- return ip_set_eexist(ret, flags) ? 0 : ret;
- }
-
- ip = ntohl(data.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);
- } else if (tb[IPSET_ATTR_CIDR]) {
- u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
-
- if (cidr > 32)
- return -IPSET_ERR_INVALID_CIDR;
- ip_set_mask_from_to(ip, ip_to, cidr);
- } else
- ip_to = ip;
-
- 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);
- }
-
- if (retried)
- ip = h->next.ip;
- for (; !before(ip_to, ip); ip++) {
- p = retried && ip == h->next.ip ? h->next.port : port;
- for (; p <= port_to; p++) {
- data.ip = htonl(ip);
- data.port = htons(p);
- ret = adtfn(set, &data, timeout, flags);
-
- if (ret && !ip_set_eexist(ret, flags))
- return ret;
- else
- ret = 0;
- }
- }
- return ret;
-}
-
-static bool
-hash_ipportip_same_set(const struct ip_set *a, const struct ip_set *b)
-{
- const struct ip_set_hash *x = a->data;
- const struct ip_set_hash *y = b->data;
-
- /* Resizing changes htable_bits, so we ignore it */
- return x->maxelem == y->maxelem &&
- x->timeout == y->timeout;
-}
-
-/* The type variant functions: IPv6 */
-
-struct hash_ipportip6_elem {
- union nf_inet_addr ip;
- union nf_inet_addr ip2;
- __be16 port;
- u8 proto;
- u8 padding;
-};
-
-struct hash_ipportip6_telem {
- union nf_inet_addr ip;
- union nf_inet_addr ip2;
- __be16 port;
- u8 proto;
- u8 padding;
- unsigned long timeout;
-};
-
-static inline bool
-hash_ipportip6_data_equal(const struct hash_ipportip6_elem *ip1,
- const struct hash_ipportip6_elem *ip2,
- u32 *multi)
-{
- return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
- ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 &&
- ip1->port == ip2->port &&
- ip1->proto == ip2->proto;
-}
-
-static inline bool
-hash_ipportip6_data_isnull(const struct hash_ipportip6_elem *elem)
-{
- return elem->proto == 0;
-}
-
-static inline void
-hash_ipportip6_data_copy(struct hash_ipportip6_elem *dst,
- const struct hash_ipportip6_elem *src)
-{
- memcpy(dst, src, sizeof(*dst));
-}
-
-static inline void
-hash_ipportip6_data_zero_out(struct hash_ipportip6_elem *elem)
-{
- elem->proto = 0;
-}
-
-static bool
-hash_ipportip6_data_list(struct sk_buff *skb,
- const struct hash_ipportip6_elem *data)
-{
- NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
- NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2);
- NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
- NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
- return 0;
-
-nla_put_failure:
- return 1;
-}
-
-static bool
-hash_ipportip6_data_tlist(struct sk_buff *skb,
- const struct hash_ipportip6_elem *data)
-{
- const struct hash_ipportip6_telem *e =
- (const struct hash_ipportip6_telem *)data;
-
- NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
- NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2);
- NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
- NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
- NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
- htonl(ip_set_timeout_get(e->timeout)));
- return 0;
-
-nla_put_failure:
- return 1;
-}
-
-#undef PF
-#undef HOST_MASK
-
-#define PF 6
-#define HOST_MASK 128
-#include "ip_set_ahash.h"
-
-static inline void
-hash_ipportip6_data_next(struct ip_set_hash *h,
- const struct hash_ipportip6_elem *d)
-{
- h->next.port = ntohs(d->port);
-}
-
-static int
-hash_ipportip6_kadt(struct ip_set *set, const struct sk_buff *skb,
- const struct xt_action_param *par,
- enum ipset_adt adt, const struct ip_set_adt_opt *opt)
-{
- const struct ip_set_hash *h = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- struct hash_ipportip6_elem data = { };
-
- if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
- &data.port, &data.proto))
- return -EINVAL;
-
- ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
- ip6addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &data.ip2.in6);
-
- return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
-}
-
-static int
-hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
-{
- const struct ip_set_hash *h = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- 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] ||
- !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) ||
- tb[IPSET_ATTR_IP_TO] ||
- tb[IPSET_ATTR_CIDR]))
- return -IPSET_ERR_PROTOCOL;
-
- if (tb[IPSET_ATTR_LINENO])
- *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
-
- ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
- if (ret)
- return ret;
-
- ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &data.ip2);
- if (ret)
- return ret;
-
- if (tb[IPSET_ATTR_PORT])
- data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
- else
- return -IPSET_ERR_PROTOCOL;
-
- 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;
-
- if (!(with_ports || data.proto == IPPROTO_ICMPV6))
- data.port = 0;
-
- if (tb[IPSET_ATTR_TIMEOUT]) {
- if (!with_timeout(h->timeout))
- return -IPSET_ERR_TIMEOUT;
- timeout = ip_set_timeout_uget(tb[IPSET_ATTR_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;
- }
-
- port = ntohs(data.port);
- port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
- if (port > port_to)
- swap(port, port_to);
-
- if (retried)
- port = h->next.port;
- for (; port <= port_to; port++) {
- data.port = htons(port);
- ret = adtfn(set, &data, timeout, flags);
-
- if (ret && !ip_set_eexist(ret, flags))
- return ret;
- else
- ret = 0;
- }
- return ret;
-}
-
-/* Create hash:ip type of sets */
-
-static int
-hash_ipportip_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
-{
- struct ip_set_hash *h;
- u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
- u8 hbits;
-
- if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
- return -IPSET_ERR_INVALID_FAMILY;
-
- 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)))
- return -IPSET_ERR_PROTOCOL;
-
- if (tb[IPSET_ATTR_HASHSIZE]) {
- hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
- if (hashsize < IPSET_MIMINAL_HASHSIZE)
- hashsize = IPSET_MIMINAL_HASHSIZE;
- }
-
- if (tb[IPSET_ATTR_MAXELEM])
- maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
-
- h = kzalloc(sizeof(*h), GFP_KERNEL);
- if (!h)
- return -ENOMEM;
-
- h->maxelem = maxelem;
- get_random_bytes(&h->initval, sizeof(h->initval));
- h->timeout = IPSET_NO_TIMEOUT;
-
- hbits = htable_bits(hashsize);
- h->table = ip_set_alloc(
- sizeof(struct htable)
- + jhash_size(hbits) * sizeof(struct hbucket));
- if (!h->table) {
- kfree(h);
- return -ENOMEM;
- }
- h->table->htable_bits = hbits;
-
- set->data = h;
-
- if (tb[IPSET_ATTR_TIMEOUT]) {
- h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
-
- set->variant = set->family == NFPROTO_IPV4
- ? &hash_ipportip4_tvariant : &hash_ipportip6_tvariant;
-
- if (set->family == NFPROTO_IPV4)
- hash_ipportip4_gc_init(set);
- else
- hash_ipportip6_gc_init(set);
- } else {
- set->variant = set->family == NFPROTO_IPV4
- ? &hash_ipportip4_variant : &hash_ipportip6_variant;
- }
-
- pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
- set->name, jhash_size(h->table->htable_bits),
- h->table->htable_bits, h->maxelem, set->data, h->table);
-
- return 0;
-}
-
-static struct ip_set_type hash_ipportip_type __read_mostly = {
- .name = "hash:ip,port,ip",
- .protocol = IPSET_PROTOCOL,
- .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2,
- .dimension = IPSET_DIM_THREE,
- .family = NFPROTO_UNSPEC,
- .revision_min = 0,
- .revision_max = 1, /* SCTP and UDPLITE support added */
- .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,
-};
-
-static int __init
-hash_ipportip_init(void)
-{
- return ip_set_type_register(&hash_ipportip_type);
-}
-
-static void __exit
-hash_ipportip_fini(void)
-{
- ip_set_type_unregister(&hash_ipportip_type);
-}
-
-module_init(hash_ipportip_init);
-module_exit(hash_ipportip_fini);
+++ /dev/null
-/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/* Kernel module implementing an IP set type: the hash:ip,port,net type */
-
-#include "jhash.h"
-#include <linux/module.h>
-#include <linux/ip.h>
-#include <linux/skbuff.h>
-#include <linux/errno.h>
-#include <linux/random.h>
-#include <net/ip.h>
-#include <net/ipv6.h>
-#include <net/netlink.h>
-#include <net/tcp.h>
-
-#include <linux/netfilter.h>
-#include "pfxlen.h"
-#include "ip_set.h"
-#include "ip_set_timeout.h"
-#include "ip_set_getport.h"
-#include "ip_set_hash.h"
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
-MODULE_DESCRIPTION("hash:ip,port,net type of IP sets");
-MODULE_ALIAS("ip_set_hash:ip,port,net");
-
-/* Type specific function prefix */
-#define TYPE hash_ipportnet
-
-static bool
-hash_ipportnet_same_set(const struct ip_set *a, const struct ip_set *b);
-
-#define hash_ipportnet4_same_set hash_ipportnet_same_set
-#define hash_ipportnet6_same_set hash_ipportnet_same_set
-
-/* The type variant functions: IPv4 */
-
-/* Member elements without timeout */
-struct hash_ipportnet4_elem {
- __be32 ip;
- __be32 ip2;
- __be16 port;
- u8 cidr;
- u8 proto;
-};
-
-/* Member elements with timeout support */
-struct hash_ipportnet4_telem {
- __be32 ip;
- __be32 ip2;
- __be16 port;
- u8 cidr;
- u8 proto;
- unsigned long timeout;
-};
-
-static inline bool
-hash_ipportnet4_data_equal(const struct hash_ipportnet4_elem *ip1,
- const struct hash_ipportnet4_elem *ip2,
- u32 *multi)
-{
- return ip1->ip == ip2->ip &&
- ip1->ip2 == ip2->ip2 &&
- ip1->cidr == ip2->cidr &&
- ip1->port == ip2->port &&
- ip1->proto == ip2->proto;
-}
-
-static inline bool
-hash_ipportnet4_data_isnull(const struct hash_ipportnet4_elem *elem)
-{
- return elem->proto == 0;
-}
-
-static inline void
-hash_ipportnet4_data_copy(struct hash_ipportnet4_elem *dst,
- const struct hash_ipportnet4_elem *src)
-{
- memcpy(dst, src, sizeof(*dst));
-}
-
-static inline void
-hash_ipportnet4_data_netmask(struct hash_ipportnet4_elem *elem, u8 cidr)
-{
- elem->ip2 &= ip_set_netmask(cidr);
- elem->cidr = cidr;
-}
-
-static inline void
-hash_ipportnet4_data_zero_out(struct hash_ipportnet4_elem *elem)
-{
- elem->proto = 0;
-}
-
-static bool
-hash_ipportnet4_data_list(struct sk_buff *skb,
- const struct hash_ipportnet4_elem *data)
-{
- NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
- NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, data->ip2);
- NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
- NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr);
- NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
- return 0;
-
-nla_put_failure:
- return 1;
-}
-
-static bool
-hash_ipportnet4_data_tlist(struct sk_buff *skb,
- const struct hash_ipportnet4_elem *data)
-{
- const struct hash_ipportnet4_telem *tdata =
- (const struct hash_ipportnet4_telem *)data;
-
- NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
- NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP2, tdata->ip2);
- NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port);
- NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr);
- NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
- NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
- htonl(ip_set_timeout_get(tdata->timeout)));
-
- return 0;
-
-nla_put_failure:
- return 1;
-}
-
-#define IP_SET_HASH_WITH_PROTO
-#define IP_SET_HASH_WITH_NETS
-
-#define PF 4
-#define HOST_MASK 32
-#include "ip_set_ahash.h"
-
-static inline void
-hash_ipportnet4_data_next(struct ip_set_hash *h,
- const struct hash_ipportnet4_elem *d)
-{
- h->next.ip = ntohl(d->ip);
- h->next.port = ntohs(d->port);
- h->next.ip2 = ntohl(d->ip2);
-}
-
-static int
-hash_ipportnet4_kadt(struct ip_set *set, const struct sk_buff *skb,
- const struct xt_action_param *par,
- enum ipset_adt adt, const struct ip_set_adt_opt *opt)
-{
- const struct ip_set_hash *h = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- struct hash_ipportnet4_elem data = {
- .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
- };
-
- if (data.cidr == 0)
- return -EINVAL;
- if (adt == IPSET_TEST)
- data.cidr = HOST_MASK;
-
- if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
- &data.port, &data.proto))
- return -EINVAL;
-
- ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
- ip4addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &data.ip2);
- data.ip2 &= ip_set_netmask(data.cidr);
-
- return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
-}
-
-static int
-hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
-{
- const struct ip_set_hash *h = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- struct hash_ipportnet4_elem data = { .cidr = HOST_MASK };
- u32 ip, ip_to = 0, p = 0, port, port_to;
- u32 ip2_from = 0, ip2_to, ip2_last, ip2;
- u32 timeout = h->timeout;
- bool with_ports = false;
- int ret;
-
- 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)))
- 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;
-
- ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2], &ip2_from);
- if (ret)
- return ret;
-
- if (tb[IPSET_ATTR_CIDR2]) {
- data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]);
- if (!data.cidr)
- return -IPSET_ERR_INVALID_CIDR;
- }
-
- if (tb[IPSET_ATTR_PORT])
- data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
- else
- return -IPSET_ERR_PROTOCOL;
-
- 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;
-
- if (!(with_ports || data.proto == IPPROTO_ICMP))
- data.port = 0;
-
- if (tb[IPSET_ATTR_TIMEOUT]) {
- if (!with_timeout(h->timeout))
- return -IPSET_ERR_TIMEOUT;
- timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
- }
-
- with_ports = with_ports && tb[IPSET_ATTR_PORT_TO];
- if (adt == IPSET_TEST ||
- !(tb[IPSET_ATTR_CIDR] || tb[IPSET_ATTR_IP_TO] || with_ports ||
- tb[IPSET_ATTR_IP2_TO])) {
- data.ip = htonl(ip);
- data.ip2 = htonl(ip2_from & ip_set_hostmask(data.cidr));
- ret = adtfn(set, &data, timeout, flags);
- return ip_set_eexist(ret, flags) ? 0 : ret;
- }
-
- 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);
- } else if (tb[IPSET_ATTR_CIDR]) {
- u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
-
- if (cidr > 32)
- return -IPSET_ERR_INVALID_CIDR;
- ip_set_mask_from_to(ip, ip_to, cidr);
- }
-
- port_to = port = ntohs(data.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 (tb[IPSET_ATTR_IP2_TO]) {
- ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2_TO], &ip2_to);
- if (ret)
- return ret;
- if (ip2_from > ip2_to)
- swap(ip2_from, ip2_to);
- if (ip2_from + UINT_MAX == ip2_to)
- return -IPSET_ERR_HASH_RANGE;
- } else {
- ip_set_mask_from_to(ip2_from, ip2_to, data.cidr);
- }
-
- if (retried)
- ip = h->next.ip;
- for (; !before(ip_to, ip); ip++) {
- data.ip = htonl(ip);
- p = retried && ip == h->next.ip ? h->next.port : port;
- for (; p <= port_to; p++) {
- data.port = htons(p);
- ip2 = retried && ip == h->next.ip && p == h->next.port
- ? h->next.ip2 : ip2_from;
- while (!after(ip2, ip2_to)) {
- data.ip2 = htonl(ip2);
- ip2_last = ip_set_range_to_cidr(ip2, ip2_to,
- &data.cidr);
- ret = adtfn(set, &data, timeout, flags);
-
- if (ret && !ip_set_eexist(ret, flags))
- return ret;
- else
- ret = 0;
- ip2 = ip2_last + 1;
- }
- }
- }
- return ret;
-}
-
-static bool
-hash_ipportnet_same_set(const struct ip_set *a, const struct ip_set *b)
-{
- const struct ip_set_hash *x = a->data;
- const struct ip_set_hash *y = b->data;
-
- /* Resizing changes htable_bits, so we ignore it */
- return x->maxelem == y->maxelem &&
- x->timeout == y->timeout;
-}
-
-/* The type variant functions: IPv6 */
-
-struct hash_ipportnet6_elem {
- union nf_inet_addr ip;
- union nf_inet_addr ip2;
- __be16 port;
- u8 cidr;
- u8 proto;
-};
-
-struct hash_ipportnet6_telem {
- union nf_inet_addr ip;
- union nf_inet_addr ip2;
- __be16 port;
- u8 cidr;
- u8 proto;
- unsigned long timeout;
-};
-
-static inline bool
-hash_ipportnet6_data_equal(const struct hash_ipportnet6_elem *ip1,
- const struct hash_ipportnet6_elem *ip2,
- u32 *multi)
-{
- return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
- ipv6_addr_cmp(&ip1->ip2.in6, &ip2->ip2.in6) == 0 &&
- ip1->cidr == ip2->cidr &&
- ip1->port == ip2->port &&
- ip1->proto == ip2->proto;
-}
-
-static inline bool
-hash_ipportnet6_data_isnull(const struct hash_ipportnet6_elem *elem)
-{
- return elem->proto == 0;
-}
-
-static inline void
-hash_ipportnet6_data_copy(struct hash_ipportnet6_elem *dst,
- const struct hash_ipportnet6_elem *src)
-{
- memcpy(dst, src, sizeof(*dst));
-}
-
-static inline void
-hash_ipportnet6_data_zero_out(struct hash_ipportnet6_elem *elem)
-{
- elem->proto = 0;
-}
-
-static inline void
-ip6_netmask(union nf_inet_addr *ip, u8 prefix)
-{
- ip->ip6[0] &= ip_set_netmask6(prefix)[0];
- ip->ip6[1] &= ip_set_netmask6(prefix)[1];
- ip->ip6[2] &= ip_set_netmask6(prefix)[2];
- ip->ip6[3] &= ip_set_netmask6(prefix)[3];
-}
-
-static inline void
-hash_ipportnet6_data_netmask(struct hash_ipportnet6_elem *elem, u8 cidr)
-{
- ip6_netmask(&elem->ip2, cidr);
- elem->cidr = cidr;
-}
-
-static bool
-hash_ipportnet6_data_list(struct sk_buff *skb,
- const struct hash_ipportnet6_elem *data)
-{
- NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
- NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2);
- NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
- NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr);
- NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
- return 0;
-
-nla_put_failure:
- return 1;
-}
-
-static bool
-hash_ipportnet6_data_tlist(struct sk_buff *skb,
- const struct hash_ipportnet6_elem *data)
-{
- const struct hash_ipportnet6_telem *e =
- (const struct hash_ipportnet6_telem *)data;
-
- NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
- NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP2, &data->ip2);
- NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
- NLA_PUT_U8(skb, IPSET_ATTR_CIDR2, data->cidr);
- NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
- NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
- htonl(ip_set_timeout_get(e->timeout)));
- return 0;
-
-nla_put_failure:
- return 1;
-}
-
-#undef PF
-#undef HOST_MASK
-
-#define PF 6
-#define HOST_MASK 128
-#include "ip_set_ahash.h"
-
-static inline void
-hash_ipportnet6_data_next(struct ip_set_hash *h,
- const struct hash_ipportnet6_elem *d)
-{
- h->next.port = ntohs(d->port);
-}
-
-static int
-hash_ipportnet6_kadt(struct ip_set *set, const struct sk_buff *skb,
- const struct xt_action_param *par,
- enum ipset_adt adt, const struct ip_set_adt_opt *opt)
-{
- const struct ip_set_hash *h = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- struct hash_ipportnet6_elem data = {
- .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
- };
-
- if (data.cidr == 0)
- return -EINVAL;
- if (adt == IPSET_TEST)
- data.cidr = HOST_MASK;
-
- if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
- &data.port, &data.proto))
- return -EINVAL;
-
- ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
- ip6addrptr(skb, opt->flags & IPSET_DIM_THREE_SRC, &data.ip2.in6);
- ip6_netmask(&data.ip2, data.cidr);
-
- return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
-}
-
-static int
-hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
-{
- const struct ip_set_hash *h = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- 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] ||
- !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) ||
- tb[IPSET_ATTR_IP_TO] ||
- tb[IPSET_ATTR_CIDR]))
- return -IPSET_ERR_PROTOCOL;
- if (unlikely(tb[IPSET_ATTR_IP_TO]))
- return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
-
- if (tb[IPSET_ATTR_LINENO])
- *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
-
- ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
- if (ret)
- return ret;
-
- ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP2], &data.ip2);
- if (ret)
- return ret;
-
- if (tb[IPSET_ATTR_CIDR2])
- data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR2]);
-
- if (!data.cidr)
- return -IPSET_ERR_INVALID_CIDR;
-
- ip6_netmask(&data.ip2, data.cidr);
-
- if (tb[IPSET_ATTR_PORT])
- data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
- else
- return -IPSET_ERR_PROTOCOL;
-
- 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;
-
- if (!(with_ports || data.proto == IPPROTO_ICMPV6))
- data.port = 0;
-
- if (tb[IPSET_ATTR_TIMEOUT]) {
- if (!with_timeout(h->timeout))
- return -IPSET_ERR_TIMEOUT;
- timeout = ip_set_timeout_uget(tb[IPSET_ATTR_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;
- }
-
- port = ntohs(data.port);
- port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
- if (port > port_to)
- swap(port, port_to);
-
- if (retried)
- port = h->next.port;
- for (; port <= port_to; port++) {
- data.port = htons(port);
- ret = adtfn(set, &data, timeout, flags);
-
- if (ret && !ip_set_eexist(ret, flags))
- return ret;
- else
- ret = 0;
- }
- return ret;
-}
-
-/* Create hash:ip type of sets */
-
-static int
-hash_ipportnet_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
-{
- struct ip_set_hash *h;
- u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
- u8 hbits;
-
- if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
- return -IPSET_ERR_INVALID_FAMILY;
-
- 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)))
- return -IPSET_ERR_PROTOCOL;
-
- if (tb[IPSET_ATTR_HASHSIZE]) {
- hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
- if (hashsize < IPSET_MIMINAL_HASHSIZE)
- hashsize = IPSET_MIMINAL_HASHSIZE;
- }
-
- if (tb[IPSET_ATTR_MAXELEM])
- maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
-
- h = kzalloc(sizeof(*h)
- + sizeof(struct ip_set_hash_nets)
- * (set->family == NFPROTO_IPV4 ? 32 : 128), GFP_KERNEL);
- if (!h)
- return -ENOMEM;
-
- h->maxelem = maxelem;
- get_random_bytes(&h->initval, sizeof(h->initval));
- h->timeout = IPSET_NO_TIMEOUT;
-
- hbits = htable_bits(hashsize);
- h->table = ip_set_alloc(
- sizeof(struct htable)
- + jhash_size(hbits) * sizeof(struct hbucket));
- if (!h->table) {
- kfree(h);
- return -ENOMEM;
- }
- h->table->htable_bits = hbits;
-
- set->data = h;
-
- if (tb[IPSET_ATTR_TIMEOUT]) {
- h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
-
- set->variant = set->family == NFPROTO_IPV4
- ? &hash_ipportnet4_tvariant
- : &hash_ipportnet6_tvariant;
-
- if (set->family == NFPROTO_IPV4)
- hash_ipportnet4_gc_init(set);
- else
- hash_ipportnet6_gc_init(set);
- } else {
- set->variant = set->family == NFPROTO_IPV4
- ? &hash_ipportnet4_variant : &hash_ipportnet6_variant;
- }
-
- pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
- set->name, jhash_size(h->table->htable_bits),
- h->table->htable_bits, h->maxelem, set->data, h->table);
-
- return 0;
-}
-
-static struct ip_set_type hash_ipportnet_type __read_mostly = {
- .name = "hash:ip,port,net",
- .protocol = IPSET_PROTOCOL,
- .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2,
- .dimension = IPSET_DIM_THREE,
- .family = NFPROTO_UNSPEC,
- .revision_min = 0,
- /* 1 SCTP and UDPLITE support added */
- .revision_max = 2, /* Range as input support for IPv4 added */
- .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_IP2_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_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,
-};
-
-static int __init
-hash_ipportnet_init(void)
-{
- return ip_set_type_register(&hash_ipportnet_type);
-}
-
-static void __exit
-hash_ipportnet_fini(void)
-{
- ip_set_type_unregister(&hash_ipportnet_type);
-}
-
-module_init(hash_ipportnet_init);
-module_exit(hash_ipportnet_fini);
+++ /dev/null
-/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/* Kernel module implementing an IP set type: the hash:net type */
-
-#include "jhash.h"
-#include <linux/module.h>
-#include <linux/ip.h>
-#include <linux/skbuff.h>
-#include <linux/errno.h>
-#include <linux/random.h>
-#include <net/ip.h>
-#include <net/ipv6.h>
-#include <net/netlink.h>
-
-#include <linux/netfilter.h>
-#include "pfxlen.h"
-#include "ip_set.h"
-#include "ip_set_timeout.h"
-#include "ip_set_hash.h"
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
-MODULE_DESCRIPTION("hash:net type of IP sets");
-MODULE_ALIAS("ip_set_hash:net");
-
-/* Type specific function prefix */
-#define TYPE hash_net
-
-static bool
-hash_net_same_set(const struct ip_set *a, const struct ip_set *b);
-
-#define hash_net4_same_set hash_net_same_set
-#define hash_net6_same_set hash_net_same_set
-
-/* The type variant functions: IPv4 */
-
-/* Member elements without timeout */
-struct hash_net4_elem {
- __be32 ip;
- u16 padding0;
- u8 padding1;
- u8 cidr;
-};
-
-/* Member elements with timeout support */
-struct hash_net4_telem {
- __be32 ip;
- u16 padding0;
- u8 padding1;
- u8 cidr;
- unsigned long timeout;
-};
-
-static inline bool
-hash_net4_data_equal(const struct hash_net4_elem *ip1,
- const struct hash_net4_elem *ip2,
- u32 *multi)
-{
- return ip1->ip == ip2->ip && ip1->cidr == ip2->cidr;
-}
-
-static inline bool
-hash_net4_data_isnull(const struct hash_net4_elem *elem)
-{
- return elem->cidr == 0;
-}
-
-static inline void
-hash_net4_data_copy(struct hash_net4_elem *dst,
- const struct hash_net4_elem *src)
-{
- dst->ip = src->ip;
- dst->cidr = src->cidr;
-}
-
-static inline void
-hash_net4_data_netmask(struct hash_net4_elem *elem, u8 cidr)
-{
- elem->ip &= ip_set_netmask(cidr);
- elem->cidr = cidr;
-}
-
-/* Zero CIDR values cannot be stored */
-static inline void
-hash_net4_data_zero_out(struct hash_net4_elem *elem)
-{
- elem->cidr = 0;
-}
-
-static bool
-hash_net4_data_list(struct sk_buff *skb, const struct hash_net4_elem *data)
-{
- NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
- NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
- return 0;
-
-nla_put_failure:
- return 1;
-}
-
-static bool
-hash_net4_data_tlist(struct sk_buff *skb, const struct hash_net4_elem *data)
-{
- const struct hash_net4_telem *tdata =
- (const struct hash_net4_telem *)data;
-
- NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
- NLA_PUT_U8(skb, IPSET_ATTR_CIDR, tdata->cidr);
- NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
- htonl(ip_set_timeout_get(tdata->timeout)));
-
- return 0;
-
-nla_put_failure:
- return 1;
-}
-
-#define IP_SET_HASH_WITH_NETS
-
-#define PF 4
-#define HOST_MASK 32
-#include "ip_set_ahash.h"
-
-static inline void
-hash_net4_data_next(struct ip_set_hash *h,
- const struct hash_net4_elem *d)
-{
- h->next.ip = ntohl(d->ip);
-}
-
-static int
-hash_net4_kadt(struct ip_set *set, const struct sk_buff *skb,
- const struct xt_action_param *par,
- enum ipset_adt adt, const struct ip_set_adt_opt *opt)
-{
- const struct ip_set_hash *h = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- struct hash_net4_elem data = {
- .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
- };
-
- if (data.cidr == 0)
- return -EINVAL;
- if (adt == IPSET_TEST)
- data.cidr = HOST_MASK;
-
- ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
- data.ip &= ip_set_netmask(data.cidr);
-
- return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
-}
-
-static int
-hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
-{
- const struct ip_set_hash *h = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- struct hash_net4_elem data = { .cidr = HOST_MASK };
- u32 timeout = h->timeout;
- u32 ip = 0, ip_to, last;
- int ret;
-
- 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 (tb[IPSET_ATTR_CIDR]) {
- data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
- if (!data.cidr)
- return -IPSET_ERR_INVALID_CIDR;
- }
-
- if (tb[IPSET_ATTR_TIMEOUT]) {
- if (!with_timeout(h->timeout))
- return -IPSET_ERR_TIMEOUT;
- timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
- }
-
- if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) {
- data.ip = htonl(ip & ip_set_hostmask(data.cidr));
- ret = adtfn(set, &data, timeout, flags);
- return ip_set_eexist(ret, flags) ? 0 : ret;
- }
-
- ip_to = 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_to < ip)
- swap(ip, ip_to);
- if (ip + UINT_MAX == ip_to)
- return -IPSET_ERR_HASH_RANGE;
- }
- if (retried)
- ip = h->next.ip;
- while (!after(ip, ip_to)) {
- data.ip = htonl(ip);
- last = ip_set_range_to_cidr(ip, ip_to, &data.cidr);
- ret = adtfn(set, &data, timeout, flags);
- if (ret && !ip_set_eexist(ret, flags))
- return ret;
- else
- ret = 0;
- ip = last + 1;
- }
- return ret;
-}
-
-static bool
-hash_net_same_set(const struct ip_set *a, const struct ip_set *b)
-{
- const struct ip_set_hash *x = a->data;
- const struct ip_set_hash *y = b->data;
-
- /* Resizing changes htable_bits, so we ignore it */
- return x->maxelem == y->maxelem &&
- x->timeout == y->timeout;
-}
-
-/* The type variant functions: IPv6 */
-
-struct hash_net6_elem {
- union nf_inet_addr ip;
- u16 padding0;
- u8 padding1;
- u8 cidr;
-};
-
-struct hash_net6_telem {
- union nf_inet_addr ip;
- u16 padding0;
- u8 padding1;
- u8 cidr;
- unsigned long timeout;
-};
-
-static inline bool
-hash_net6_data_equal(const struct hash_net6_elem *ip1,
- const struct hash_net6_elem *ip2,
- u32 *multi)
-{
- return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
- ip1->cidr == ip2->cidr;
-}
-
-static inline bool
-hash_net6_data_isnull(const struct hash_net6_elem *elem)
-{
- return elem->cidr == 0;
-}
-
-static inline void
-hash_net6_data_copy(struct hash_net6_elem *dst,
- const struct hash_net6_elem *src)
-{
- dst->ip.in6 = src->ip.in6;
- dst->cidr = src->cidr;
-}
-
-static inline void
-hash_net6_data_zero_out(struct hash_net6_elem *elem)
-{
- elem->cidr = 0;
-}
-
-static inline void
-ip6_netmask(union nf_inet_addr *ip, u8 prefix)
-{
- ip->ip6[0] &= ip_set_netmask6(prefix)[0];
- ip->ip6[1] &= ip_set_netmask6(prefix)[1];
- ip->ip6[2] &= ip_set_netmask6(prefix)[2];
- ip->ip6[3] &= ip_set_netmask6(prefix)[3];
-}
-
-static inline void
-hash_net6_data_netmask(struct hash_net6_elem *elem, u8 cidr)
-{
- ip6_netmask(&elem->ip, cidr);
- elem->cidr = cidr;
-}
-
-static bool
-hash_net6_data_list(struct sk_buff *skb, const struct hash_net6_elem *data)
-{
- NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
- NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
- return 0;
-
-nla_put_failure:
- return 1;
-}
-
-static bool
-hash_net6_data_tlist(struct sk_buff *skb, const struct hash_net6_elem *data)
-{
- const struct hash_net6_telem *e =
- (const struct hash_net6_telem *)data;
-
- NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
- NLA_PUT_U8(skb, IPSET_ATTR_CIDR, e->cidr);
- NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
- htonl(ip_set_timeout_get(e->timeout)));
- return 0;
-
-nla_put_failure:
- return 1;
-}
-
-#undef PF
-#undef HOST_MASK
-
-#define PF 6
-#define HOST_MASK 128
-#include "ip_set_ahash.h"
-
-static inline void
-hash_net6_data_next(struct ip_set_hash *h,
- const struct hash_net6_elem *d)
-{
-}
-
-static int
-hash_net6_kadt(struct ip_set *set, const struct sk_buff *skb,
- const struct xt_action_param *par,
- enum ipset_adt adt, const struct ip_set_adt_opt *opt)
-{
- const struct ip_set_hash *h = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- struct hash_net6_elem data = {
- .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
- };
-
- if (data.cidr == 0)
- return -EINVAL;
- if (adt == IPSET_TEST)
- data.cidr = HOST_MASK;
-
- ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
- ip6_netmask(&data.ip, data.cidr);
-
- return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
-}
-
-static int
-hash_net6_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
-{
- const struct ip_set_hash *h = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- struct hash_net6_elem data = { .cidr = HOST_MASK };
- u32 timeout = h->timeout;
- int ret;
-
- if (unlikely(!tb[IPSET_ATTR_IP] ||
- !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
- return -IPSET_ERR_PROTOCOL;
- if (unlikely(tb[IPSET_ATTR_IP_TO]))
- return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
-
- if (tb[IPSET_ATTR_LINENO])
- *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
-
- ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
- if (ret)
- return ret;
-
- if (tb[IPSET_ATTR_CIDR])
- data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
-
- if (!data.cidr)
- return -IPSET_ERR_INVALID_CIDR;
-
- ip6_netmask(&data.ip, data.cidr);
-
- if (tb[IPSET_ATTR_TIMEOUT]) {
- if (!with_timeout(h->timeout))
- return -IPSET_ERR_TIMEOUT;
- timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
- }
-
- ret = adtfn(set, &data, timeout, flags);
-
- return ip_set_eexist(ret, flags) ? 0 : ret;
-}
-
-/* Create hash:ip type of sets */
-
-static int
-hash_net_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
-{
- u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
- struct ip_set_hash *h;
- u8 hbits;
-
- if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
- return -IPSET_ERR_INVALID_FAMILY;
-
- 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)))
- return -IPSET_ERR_PROTOCOL;
-
- if (tb[IPSET_ATTR_HASHSIZE]) {
- hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
- if (hashsize < IPSET_MIMINAL_HASHSIZE)
- hashsize = IPSET_MIMINAL_HASHSIZE;
- }
-
- if (tb[IPSET_ATTR_MAXELEM])
- maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
-
- h = kzalloc(sizeof(*h)
- + sizeof(struct ip_set_hash_nets)
- * (set->family == NFPROTO_IPV4 ? 32 : 128), GFP_KERNEL);
- if (!h)
- return -ENOMEM;
-
- h->maxelem = maxelem;
- get_random_bytes(&h->initval, sizeof(h->initval));
- h->timeout = IPSET_NO_TIMEOUT;
-
- hbits = htable_bits(hashsize);
- h->table = ip_set_alloc(
- sizeof(struct htable)
- + jhash_size(hbits) * sizeof(struct hbucket));
- if (!h->table) {
- kfree(h);
- return -ENOMEM;
- }
- h->table->htable_bits = hbits;
-
- set->data = h;
-
- if (tb[IPSET_ATTR_TIMEOUT]) {
- h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
-
- set->variant = set->family == NFPROTO_IPV4
- ? &hash_net4_tvariant : &hash_net6_tvariant;
-
- if (set->family == NFPROTO_IPV4)
- hash_net4_gc_init(set);
- else
- hash_net6_gc_init(set);
- } else {
- set->variant = set->family == NFPROTO_IPV4
- ? &hash_net4_variant : &hash_net6_variant;
- }
-
- pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
- set->name, jhash_size(h->table->htable_bits),
- h->table->htable_bits, h->maxelem, set->data, h->table);
-
- return 0;
-}
-
-static struct ip_set_type hash_net_type __read_mostly = {
- .name = "hash:net",
- .protocol = IPSET_PROTOCOL,
- .features = IPSET_TYPE_IP,
- .dimension = IPSET_DIM_ONE,
- .family = NFPROTO_UNSPEC,
- .revision_min = 0,
- .revision_max = 1, /* Range as input support for IPv4 added */
- .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_IP_TO] = { .type = NLA_NESTED },
- [IPSET_ATTR_CIDR] = { .type = NLA_U8 },
- [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
- },
- .me = THIS_MODULE,
-};
-
-static int __init
-hash_net_init(void)
-{
- return ip_set_type_register(&hash_net_type);
-}
-
-static void __exit
-hash_net_fini(void)
-{
- ip_set_type_unregister(&hash_net_type);
-}
-
-module_init(hash_net_init);
-module_exit(hash_net_fini);
+++ /dev/null
-/* Copyright (C) 2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/* Kernel module implementing an IP set type: the hash:net,iface type */
-
-#include "jhash.h"
-#include <linux/module.h>
-#include <linux/ip.h>
-#include <linux/skbuff.h>
-#include <linux/errno.h>
-#include <linux/random.h>
-#include <linux/rbtree.h>
-#include <net/ip.h>
-#include <net/ipv6.h>
-#include <net/netlink.h>
-
-#include <linux/netfilter.h>
-#include "pfxlen.h"
-#include "ip_set.h"
-#include "ip_set_timeout.h"
-#include "ip_set_hash.h"
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
-MODULE_DESCRIPTION("hash:net,iface type of IP sets");
-MODULE_ALIAS("ip_set_hash:net,iface");
-
-/* Interface name rbtree */
-
-struct iface_node {
- struct rb_node node;
- char iface[IFNAMSIZ];
-};
-
-#define iface_data(n) (rb_entry(n, struct iface_node, node)->iface)
-
-static inline long
-ifname_compare(const char *_a, const char *_b)
-{
- const long *a = (const long *)_a;
- const long *b = (const long *)_b;
-
- BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long));
- if (a[0] != b[0])
- return a[0] - b[0];
- if (IFNAMSIZ > sizeof(long)) {
- if (a[1] != b[1])
- return a[1] - b[1];
- }
- if (IFNAMSIZ > 2 * sizeof(long)) {
- if (a[2] != b[2])
- return a[2] - b[2];
- }
- if (IFNAMSIZ > 3 * sizeof(long)) {
- if (a[3] != b[3])
- return a[3] - b[3];
- }
- return 0;
-}
-
-static void
-rbtree_destroy(struct rb_root *root)
-{
- struct rb_node *p, *n = root->rb_node;
- struct iface_node *node;
-
- /* Non-recursive destroy, like in ext3 */
- while (n) {
- if (n->rb_left) {
- n = n->rb_left;
- continue;
- }
- if (n->rb_right) {
- n = n->rb_right;
- continue;
- }
- p = rb_parent(n);
- node = rb_entry(n, struct iface_node, node);
- if (!p)
- *root = RB_ROOT;
- else if (p->rb_left == n)
- p->rb_left = NULL;
- else if (p->rb_right == n)
- p->rb_right = NULL;
-
- kfree(node);
- n = p;
- }
-}
-
-static int
-iface_test(struct rb_root *root, const char **iface)
-{
- struct rb_node *n = root->rb_node;
-
- while (n) {
- const char *d = iface_data(n);
- long res = ifname_compare(*iface, d);
-
- if (res < 0)
- n = n->rb_left;
- else if (res > 0)
- n = n->rb_right;
- else {
- *iface = d;
- return 1;
- }
- }
- return 0;
-}
-
-static int
-iface_add(struct rb_root *root, const char **iface)
-{
- struct rb_node **n = &(root->rb_node), *p = NULL;
- struct iface_node *d;
-
- while (*n) {
- char *ifname = iface_data(*n);
- long res = ifname_compare(*iface, ifname);
-
- p = *n;
- if (res < 0)
- n = &((*n)->rb_left);
- else if (res > 0)
- n = &((*n)->rb_right);
- else {
- *iface = ifname;
- return 0;
- }
- }
-
- d = kzalloc(sizeof(*d), GFP_ATOMIC);
- if (!d)
- return -ENOMEM;
- strcpy(d->iface, *iface);
-
- rb_link_node(&d->node, p, n);
- rb_insert_color(&d->node, root);
-
- *iface = d->iface;
- return 0;
-}
-
-/* Type specific function prefix */
-#define TYPE hash_netiface
-
-static bool
-hash_netiface_same_set(const struct ip_set *a, const struct ip_set *b);
-
-#define hash_netiface4_same_set hash_netiface_same_set
-#define hash_netiface6_same_set hash_netiface_same_set
-
-#define STREQ(a, b) (strcmp(a, b) == 0)
-
-/* The type variant functions: IPv4 */
-
-struct hash_netiface4_elem_hashed {
- __be32 ip;
- u8 physdev;
- u8 cidr;
- u16 padding;
-};
-
-#define HKEY_DATALEN sizeof(struct hash_netiface4_elem_hashed)
-
-/* Member elements without timeout */
-struct hash_netiface4_elem {
- __be32 ip;
- u8 physdev;
- u8 cidr;
- u16 padding;
- const char *iface;
-};
-
-/* Member elements with timeout support */
-struct hash_netiface4_telem {
- __be32 ip;
- u8 physdev;
- u8 cidr;
- u16 padding;
- const char *iface;
- unsigned long timeout;
-};
-
-static inline bool
-hash_netiface4_data_equal(const struct hash_netiface4_elem *ip1,
- const struct hash_netiface4_elem *ip2,
- u32 *multi)
-{
- return ip1->ip == ip2->ip &&
- ip1->cidr == ip2->cidr &&
- (++*multi) &&
- ip1->physdev == ip2->physdev &&
- ip1->iface == ip2->iface;
-}
-
-static inline bool
-hash_netiface4_data_isnull(const struct hash_netiface4_elem *elem)
-{
- return elem->cidr == 0;
-}
-
-static inline void
-hash_netiface4_data_copy(struct hash_netiface4_elem *dst,
- const struct hash_netiface4_elem *src) {
- dst->ip = src->ip;
- dst->cidr = src->cidr;
- dst->physdev = src->physdev;
- dst->iface = src->iface;
-}
-
-static inline void
-hash_netiface4_data_netmask(struct hash_netiface4_elem *elem, u8 cidr)
-{
- elem->ip &= ip_set_netmask(cidr);
- elem->cidr = cidr;
-}
-
-static inline void
-hash_netiface4_data_zero_out(struct hash_netiface4_elem *elem)
-{
- elem->cidr = 0;
-}
-
-static bool
-hash_netiface4_data_list(struct sk_buff *skb,
- const struct hash_netiface4_elem *data)
-{
- u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
-
- NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
- NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
- NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface);
- if (flags)
- NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, flags);
- return 0;
-
-nla_put_failure:
- return 1;
-}
-
-static bool
-hash_netiface4_data_tlist(struct sk_buff *skb,
- const struct hash_netiface4_elem *data)
-{
- const struct hash_netiface4_telem *tdata =
- (const struct hash_netiface4_telem *)data;
- u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
-
- NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
- NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
- NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface);
- if (flags)
- NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, flags);
- NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
- htonl(ip_set_timeout_get(tdata->timeout)));
-
- return 0;
-
-nla_put_failure:
- return 1;
-}
-
-#define IP_SET_HASH_WITH_NETS
-#define IP_SET_HASH_WITH_RBTREE
-#define IP_SET_HASH_WITH_MULTI
-
-#define PF 4
-#define HOST_MASK 32
-#include "ip_set_ahash.h"
-
-static inline void
-hash_netiface4_data_next(struct ip_set_hash *h,
- const struct hash_netiface4_elem *d)
-{
- h->next.ip = ntohl(d->ip);
-}
-
-static int
-hash_netiface4_kadt(struct ip_set *set, const struct sk_buff *skb,
- const struct xt_action_param *par,
- enum ipset_adt adt, const struct ip_set_adt_opt *opt)
-{
- struct ip_set_hash *h = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- struct hash_netiface4_elem data = {
- .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
- };
- int ret;
-
- if (data.cidr == 0)
- return -EINVAL;
- if (adt == IPSET_TEST)
- data.cidr = HOST_MASK;
-
- ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
- data.ip &= ip_set_netmask(data.cidr);
-
-#define IFACE(dir) (par->dir ? par->dir->name : NULL)
-#define PHYSDEV(dir) (nf_bridge->dir ? nf_bridge->dir->name : NULL)
-#define SRCDIR (opt->flags & IPSET_DIM_TWO_SRC)
-
- if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
-#ifdef CONFIG_BRIDGE_NETFILTER
- const struct nf_bridge_info *nf_bridge = skb->nf_bridge;
-
- if (!nf_bridge)
- return -EINVAL;
- data.iface = SRCDIR ? PHYSDEV(physindev) : PHYSDEV(physoutdev);
- data.physdev = 1;
-#else
- data.iface = NULL;
-#endif
- } else
- data.iface = SRCDIR ? IFACE(in) : IFACE(out);
-
- if (!data.iface)
- return -EINVAL;
- ret = iface_test(&h->rbtree, &data.iface);
- if (adt == IPSET_ADD) {
- if (!ret) {
- ret = iface_add(&h->rbtree, &data.iface);
- if (ret)
- return ret;
- }
- } else if (!ret)
- return ret;
-
- return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
-}
-
-static int
-hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
-{
- struct ip_set_hash *h = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- struct hash_netiface4_elem data = { .cidr = HOST_MASK };
- u32 ip = 0, ip_to, last;
- u32 timeout = h->timeout;
- char iface[IFNAMSIZ] = {};
- int ret;
-
- if (unlikely(!tb[IPSET_ATTR_IP] ||
- !tb[IPSET_ATTR_IFACE] ||
- !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
- !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
- 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 (tb[IPSET_ATTR_CIDR]) {
- data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
- if (!data.cidr)
- return -IPSET_ERR_INVALID_CIDR;
- }
-
- if (tb[IPSET_ATTR_TIMEOUT]) {
- if (!with_timeout(h->timeout))
- return -IPSET_ERR_TIMEOUT;
- timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
- }
-
- strcpy(iface, nla_data(tb[IPSET_ATTR_IFACE]));
- data.iface = iface;
- ret = iface_test(&h->rbtree, &data.iface);
- if (adt == IPSET_ADD) {
- if (!ret) {
- ret = iface_add(&h->rbtree, &data.iface);
- if (ret)
- return ret;
- }
- } else if (!ret)
- return ret;
-
- if (tb[IPSET_ATTR_CADT_FLAGS]) {
- u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
- if (cadt_flags & IPSET_FLAG_PHYSDEV)
- data.physdev = 1;
- }
-
- if (adt == IPSET_TEST || !tb[IPSET_ATTR_IP_TO]) {
- data.ip = htonl(ip & ip_set_hostmask(data.cidr));
- ret = adtfn(set, &data, timeout, flags);
- return ip_set_eexist(ret, flags) ? 0 : ret;
- }
-
- if (tb[IPSET_ATTR_IP_TO]) {
- ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
- if (ret)
- return ret;
- if (ip_to < ip)
- swap(ip, ip_to);
- if (ip + UINT_MAX == ip_to)
- return -IPSET_ERR_HASH_RANGE;
- } else {
- ip_set_mask_from_to(ip, ip_to, data.cidr);
- }
-
- if (retried)
- ip = h->next.ip;
- while (!after(ip, ip_to)) {
- data.ip = htonl(ip);
- last = ip_set_range_to_cidr(ip, ip_to, &data.cidr);
- ret = adtfn(set, &data, timeout, flags);
-
- if (ret && !ip_set_eexist(ret, flags))
- return ret;
- else
- ret = 0;
- ip = last + 1;
- }
- return ret;
-}
-
-static bool
-hash_netiface_same_set(const struct ip_set *a, const struct ip_set *b)
-{
- const struct ip_set_hash *x = a->data;
- const struct ip_set_hash *y = b->data;
-
- /* Resizing changes htable_bits, so we ignore it */
- return x->maxelem == y->maxelem &&
- x->timeout == y->timeout;
-}
-
-/* The type variant functions: IPv6 */
-
-struct hash_netiface6_elem_hashed {
- union nf_inet_addr ip;
- u8 physdev;
- u8 cidr;
- u16 padding;
-};
-
-#define HKEY_DATALEN sizeof(struct hash_netiface6_elem_hashed)
-
-struct hash_netiface6_elem {
- union nf_inet_addr ip;
- u8 physdev;
- u8 cidr;
- u16 padding;
- const char *iface;
-};
-
-struct hash_netiface6_telem {
- union nf_inet_addr ip;
- u8 physdev;
- u8 cidr;
- u16 padding;
- const char *iface;
- unsigned long timeout;
-};
-
-static inline bool
-hash_netiface6_data_equal(const struct hash_netiface6_elem *ip1,
- const struct hash_netiface6_elem *ip2,
- u32 *multi)
-{
- return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
- ip1->cidr == ip2->cidr &&
- (++*multi) &&
- ip1->physdev == ip2->physdev &&
- ip1->iface == ip2->iface;
-}
-
-static inline bool
-hash_netiface6_data_isnull(const struct hash_netiface6_elem *elem)
-{
- return elem->cidr == 0;
-}
-
-static inline void
-hash_netiface6_data_copy(struct hash_netiface6_elem *dst,
- const struct hash_netiface6_elem *src)
-{
- memcpy(dst, src, sizeof(*dst));
-}
-
-static inline void
-hash_netiface6_data_zero_out(struct hash_netiface6_elem *elem)
-{
-}
-
-static inline void
-ip6_netmask(union nf_inet_addr *ip, u8 prefix)
-{
- ip->ip6[0] &= ip_set_netmask6(prefix)[0];
- ip->ip6[1] &= ip_set_netmask6(prefix)[1];
- ip->ip6[2] &= ip_set_netmask6(prefix)[2];
- ip->ip6[3] &= ip_set_netmask6(prefix)[3];
-}
-
-static inline void
-hash_netiface6_data_netmask(struct hash_netiface6_elem *elem, u8 cidr)
-{
- ip6_netmask(&elem->ip, cidr);
- elem->cidr = cidr;
-}
-
-static bool
-hash_netiface6_data_list(struct sk_buff *skb,
- const struct hash_netiface6_elem *data)
-{
- u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
-
- NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
- NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
- NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface);
- if (flags)
- NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, flags);
- return 0;
-
-nla_put_failure:
- return 1;
-}
-
-static bool
-hash_netiface6_data_tlist(struct sk_buff *skb,
- const struct hash_netiface6_elem *data)
-{
- const struct hash_netiface6_telem *e =
- (const struct hash_netiface6_telem *)data;
- u32 flags = data->physdev ? IPSET_FLAG_PHYSDEV : 0;
-
- NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
- NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
- NLA_PUT_STRING(skb, IPSET_ATTR_IFACE, data->iface);
- if (flags)
- NLA_PUT_NET32(skb, IPSET_ATTR_CADT_FLAGS, flags);
- NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
- htonl(ip_set_timeout_get(e->timeout)));
- return 0;
-
-nla_put_failure:
- return 1;
-}
-
-#undef PF
-#undef HOST_MASK
-
-#define PF 6
-#define HOST_MASK 128
-#include "ip_set_ahash.h"
-
-static inline void
-hash_netiface6_data_next(struct ip_set_hash *h,
- const struct hash_netiface6_elem *d)
-{
-}
-
-static int
-hash_netiface6_kadt(struct ip_set *set, const struct sk_buff *skb,
- const struct xt_action_param *par,
- enum ipset_adt adt, const struct ip_set_adt_opt *opt)
-{
- struct ip_set_hash *h = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- struct hash_netiface6_elem data = {
- .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
- };
- int ret;
-
- if (data.cidr == 0)
- return -EINVAL;
- if (adt == IPSET_TEST)
- data.cidr = HOST_MASK;
-
- ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
- ip6_netmask(&data.ip, data.cidr);
-
- if (opt->cmdflags & IPSET_FLAG_PHYSDEV) {
-#ifdef CONFIG_BRIDGE_NETFILTER
- const struct nf_bridge_info *nf_bridge = skb->nf_bridge;
-
- if (!nf_bridge)
- return -EINVAL;
- data.iface = SRCDIR ? PHYSDEV(physindev) : PHYSDEV(physoutdev);
- data.physdev = 1;
-#else
- data.iface = NULL;
-#endif
- } else
- data.iface = SRCDIR ? IFACE(in) : IFACE(out);
-
- if (!data.iface)
- return -EINVAL;
- ret = iface_test(&h->rbtree, &data.iface);
- if (adt == IPSET_ADD) {
- if (!ret) {
- ret = iface_add(&h->rbtree, &data.iface);
- if (ret)
- return ret;
- }
- } else if (!ret)
- return ret;
-
- return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
-}
-
-static int
-hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
-{
- struct ip_set_hash *h = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- struct hash_netiface6_elem data = { .cidr = HOST_MASK };
- u32 timeout = h->timeout;
- char iface[IFNAMSIZ] = {};
- int ret;
-
- if (unlikely(!tb[IPSET_ATTR_IP] ||
- !tb[IPSET_ATTR_IFACE] ||
- !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
- !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
- return -IPSET_ERR_PROTOCOL;
- if (unlikely(tb[IPSET_ATTR_IP_TO]))
- return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
-
- if (tb[IPSET_ATTR_LINENO])
- *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
-
- ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
- if (ret)
- return ret;
-
- if (tb[IPSET_ATTR_CIDR])
- data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
- if (!data.cidr)
- return -IPSET_ERR_INVALID_CIDR;
- ip6_netmask(&data.ip, data.cidr);
-
- if (tb[IPSET_ATTR_TIMEOUT]) {
- if (!with_timeout(h->timeout))
- return -IPSET_ERR_TIMEOUT;
- timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
- }
-
- strcpy(iface, nla_data(tb[IPSET_ATTR_IFACE]));
- data.iface = iface;
- ret = iface_test(&h->rbtree, &data.iface);
- if (adt == IPSET_ADD) {
- if (!ret) {
- ret = iface_add(&h->rbtree, &data.iface);
- if (ret)
- return ret;
- }
- } else if (!ret)
- return ret;
-
- if (tb[IPSET_ATTR_CADT_FLAGS]) {
- u32 cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
- if (cadt_flags & IPSET_FLAG_PHYSDEV)
- data.physdev = 1;
- }
-
- ret = adtfn(set, &data, timeout, flags);
-
- return ip_set_eexist(ret, flags) ? 0 : ret;
-}
-
-/* Create hash:ip type of sets */
-
-static int
-hash_netiface_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
-{
- struct ip_set_hash *h;
- u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
- u8 hbits;
-
- if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
- return -IPSET_ERR_INVALID_FAMILY;
-
- 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)))
- return -IPSET_ERR_PROTOCOL;
-
- if (tb[IPSET_ATTR_HASHSIZE]) {
- hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
- if (hashsize < IPSET_MIMINAL_HASHSIZE)
- hashsize = IPSET_MIMINAL_HASHSIZE;
- }
-
- if (tb[IPSET_ATTR_MAXELEM])
- maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
-
- h = kzalloc(sizeof(*h)
- + sizeof(struct ip_set_hash_nets)
- * (set->family == NFPROTO_IPV4 ? 32 : 128), GFP_KERNEL);
- if (!h)
- return -ENOMEM;
-
- h->maxelem = maxelem;
- get_random_bytes(&h->initval, sizeof(h->initval));
- h->timeout = IPSET_NO_TIMEOUT;
- h->ahash_max = AHASH_MAX_SIZE;
-
- hbits = htable_bits(hashsize);
- h->table = ip_set_alloc(
- sizeof(struct htable)
- + jhash_size(hbits) * sizeof(struct hbucket));
- if (!h->table) {
- kfree(h);
- return -ENOMEM;
- }
- h->table->htable_bits = hbits;
- h->rbtree = RB_ROOT;
-
- set->data = h;
-
- if (tb[IPSET_ATTR_TIMEOUT]) {
- h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
-
- set->variant = set->family == NFPROTO_IPV4
- ? &hash_netiface4_tvariant : &hash_netiface6_tvariant;
-
- if (set->family == NFPROTO_IPV4)
- hash_netiface4_gc_init(set);
- else
- hash_netiface6_gc_init(set);
- } else {
- set->variant = set->family == NFPROTO_IPV4
- ? &hash_netiface4_variant : &hash_netiface6_variant;
- }
-
- pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
- set->name, jhash_size(h->table->htable_bits),
- h->table->htable_bits, h->maxelem, set->data, h->table);
-
- return 0;
-}
-
-static struct ip_set_type hash_netiface_type __read_mostly = {
- .name = "hash:net,iface",
- .protocol = IPSET_PROTOCOL,
- .features = IPSET_TYPE_IP | IPSET_TYPE_IFACE,
- .dimension = IPSET_DIM_TWO,
- .family = NFPROTO_UNSPEC,
- .revision_min = 0,
- .create = hash_netiface_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_IFACE] = { .type = NLA_NUL_STRING,
- .len = IPSET_MAXNAMELEN - 1 },
- [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
- [IPSET_ATTR_CIDR] = { .type = NLA_U8 },
- [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
- [IPSET_ATTR_LINENO] = { .type = NLA_U32 },
- },
- .me = THIS_MODULE,
-};
-
-static int __init
-hash_netiface_init(void)
-{
- return ip_set_type_register(&hash_netiface_type);
-}
-
-static void __exit
-hash_netiface_fini(void)
-{
- ip_set_type_unregister(&hash_netiface_type);
-}
-
-module_init(hash_netiface_init);
-module_exit(hash_netiface_fini);
+++ /dev/null
-/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/* Kernel module implementing an IP set type: the hash:net,port type */
-
-#include "jhash.h"
-#include <linux/module.h>
-#include <linux/ip.h>
-#include <linux/skbuff.h>
-#include <linux/errno.h>
-#include <linux/random.h>
-#include <net/ip.h>
-#include <net/ipv6.h>
-#include <net/netlink.h>
-
-#include <linux/netfilter.h>
-#include "pfxlen.h"
-#include "ip_set.h"
-#include "ip_set_timeout.h"
-#include "ip_set_getport.h"
-#include "ip_set_hash.h"
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
-MODULE_DESCRIPTION("hash:net,port type of IP sets");
-MODULE_ALIAS("ip_set_hash:net,port");
-
-/* Type specific function prefix */
-#define TYPE hash_netport
-
-static bool
-hash_netport_same_set(const struct ip_set *a, const struct ip_set *b);
-
-#define hash_netport4_same_set hash_netport_same_set
-#define hash_netport6_same_set hash_netport_same_set
-
-/* The type variant functions: IPv4 */
-
-/* Member elements without timeout */
-struct hash_netport4_elem {
- __be32 ip;
- __be16 port;
- u8 proto;
- u8 cidr;
-};
-
-/* Member elements with timeout support */
-struct hash_netport4_telem {
- __be32 ip;
- __be16 port;
- u8 proto;
- u8 cidr;
- unsigned long timeout;
-};
-
-static inline bool
-hash_netport4_data_equal(const struct hash_netport4_elem *ip1,
- const struct hash_netport4_elem *ip2,
- u32 *multi)
-{
- return ip1->ip == ip2->ip &&
- ip1->port == ip2->port &&
- ip1->proto == ip2->proto &&
- ip1->cidr == ip2->cidr;
-}
-
-static inline bool
-hash_netport4_data_isnull(const struct hash_netport4_elem *elem)
-{
- return elem->proto == 0;
-}
-
-static inline void
-hash_netport4_data_copy(struct hash_netport4_elem *dst,
- const struct hash_netport4_elem *src)
-{
- dst->ip = src->ip;
- dst->port = src->port;
- dst->proto = src->proto;
- dst->cidr = src->cidr;
-}
-
-static inline void
-hash_netport4_data_netmask(struct hash_netport4_elem *elem, u8 cidr)
-{
- elem->ip &= ip_set_netmask(cidr);
- elem->cidr = cidr;
-}
-
-static inline void
-hash_netport4_data_zero_out(struct hash_netport4_elem *elem)
-{
- elem->proto = 0;
-}
-
-static bool
-hash_netport4_data_list(struct sk_buff *skb,
- const struct hash_netport4_elem *data)
-{
- NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, data->ip);
- NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
- NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
- NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
- return 0;
-
-nla_put_failure:
- return 1;
-}
-
-static bool
-hash_netport4_data_tlist(struct sk_buff *skb,
- const struct hash_netport4_elem *data)
-{
- const struct hash_netport4_telem *tdata =
- (const struct hash_netport4_telem *)data;
-
- NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, tdata->ip);
- NLA_PUT_NET16(skb, IPSET_ATTR_PORT, tdata->port);
- NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
- NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
- NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
- htonl(ip_set_timeout_get(tdata->timeout)));
-
- return 0;
-
-nla_put_failure:
- return 1;
-}
-
-#define IP_SET_HASH_WITH_PROTO
-#define IP_SET_HASH_WITH_NETS
-
-#define PF 4
-#define HOST_MASK 32
-#include "ip_set_ahash.h"
-
-static inline void
-hash_netport4_data_next(struct ip_set_hash *h,
- const struct hash_netport4_elem *d)
-{
- h->next.ip = ntohl(d->ip);
- h->next.port = ntohs(d->port);
-}
-
-static int
-hash_netport4_kadt(struct ip_set *set, const struct sk_buff *skb,
- const struct xt_action_param *par,
- enum ipset_adt adt, const struct ip_set_adt_opt *opt)
-{
- const struct ip_set_hash *h = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- struct hash_netport4_elem data = {
- .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
- };
-
- if (data.cidr == 0)
- return -EINVAL;
- if (adt == IPSET_TEST)
- data.cidr = HOST_MASK;
-
- if (!ip_set_get_ip4_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
- &data.port, &data.proto))
- return -EINVAL;
-
- ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip);
- data.ip &= ip_set_netmask(data.cidr);
-
- return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
-}
-
-static int
-hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
-{
- const struct ip_set_hash *h = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- struct hash_netport4_elem data = { .cidr = HOST_MASK };
- u32 port, port_to, p = 0, ip = 0, ip_to, last;
- u32 timeout = h->timeout;
- bool with_ports = false;
- int ret;
-
- 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)))
- 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 (tb[IPSET_ATTR_CIDR]) {
- data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
- if (!data.cidr)
- return -IPSET_ERR_INVALID_CIDR;
- }
-
- if (tb[IPSET_ATTR_PORT])
- data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
- else
- return -IPSET_ERR_PROTOCOL;
-
- 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;
-
- if (!(with_ports || data.proto == IPPROTO_ICMP))
- data.port = 0;
-
- if (tb[IPSET_ATTR_TIMEOUT]) {
- if (!with_timeout(h->timeout))
- return -IPSET_ERR_TIMEOUT;
- timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
- }
-
- with_ports = with_ports && tb[IPSET_ATTR_PORT_TO];
- if (adt == IPSET_TEST || !(with_ports || tb[IPSET_ATTR_IP_TO])) {
- data.ip = htonl(ip & ip_set_hostmask(data.cidr));
- ret = adtfn(set, &data, timeout, flags);
- return ip_set_eexist(ret, flags) ? 0 : ret;
- }
-
- port = port_to = ntohs(data.port);
- if (tb[IPSET_ATTR_PORT_TO]) {
- port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
- if (port_to < port)
- swap(port, port_to);
- }
- if (tb[IPSET_ATTR_IP_TO]) {
- ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
- if (ret)
- return ret;
- if (ip_to < ip)
- swap(ip, ip_to);
- if (ip + UINT_MAX == ip_to)
- return -IPSET_ERR_HASH_RANGE;
- } else {
- ip_set_mask_from_to(ip, ip_to, data.cidr);
- }
-
- if (retried)
- ip = h->next.ip;
- while (!after(ip, ip_to)) {
- data.ip = htonl(ip);
- last = ip_set_range_to_cidr(ip, ip_to, &data.cidr);
- p = retried && ip == h->next.ip ? h->next.port : port;
- for (; p <= port_to; p++) {
- data.port = htons(p);
- ret = adtfn(set, &data, timeout, flags);
-
- if (ret && !ip_set_eexist(ret, flags))
- return ret;
- else
- ret = 0;
- }
- ip = last + 1;
- }
- return ret;
-}
-
-static bool
-hash_netport_same_set(const struct ip_set *a, const struct ip_set *b)
-{
- const struct ip_set_hash *x = a->data;
- const struct ip_set_hash *y = b->data;
-
- /* Resizing changes htable_bits, so we ignore it */
- return x->maxelem == y->maxelem &&
- x->timeout == y->timeout;
-}
-
-/* The type variant functions: IPv6 */
-
-struct hash_netport6_elem {
- union nf_inet_addr ip;
- __be16 port;
- u8 proto;
- u8 cidr;
-};
-
-struct hash_netport6_telem {
- union nf_inet_addr ip;
- __be16 port;
- u8 proto;
- u8 cidr;
- unsigned long timeout;
-};
-
-static inline bool
-hash_netport6_data_equal(const struct hash_netport6_elem *ip1,
- const struct hash_netport6_elem *ip2,
- u32 *multi)
-{
- return ipv6_addr_cmp(&ip1->ip.in6, &ip2->ip.in6) == 0 &&
- ip1->port == ip2->port &&
- ip1->proto == ip2->proto &&
- ip1->cidr == ip2->cidr;
-}
-
-static inline bool
-hash_netport6_data_isnull(const struct hash_netport6_elem *elem)
-{
- return elem->proto == 0;
-}
-
-static inline void
-hash_netport6_data_copy(struct hash_netport6_elem *dst,
- const struct hash_netport6_elem *src)
-{
- memcpy(dst, src, sizeof(*dst));
-}
-
-static inline void
-hash_netport6_data_zero_out(struct hash_netport6_elem *elem)
-{
- elem->proto = 0;
-}
-
-static inline void
-ip6_netmask(union nf_inet_addr *ip, u8 prefix)
-{
- ip->ip6[0] &= ip_set_netmask6(prefix)[0];
- ip->ip6[1] &= ip_set_netmask6(prefix)[1];
- ip->ip6[2] &= ip_set_netmask6(prefix)[2];
- ip->ip6[3] &= ip_set_netmask6(prefix)[3];
-}
-
-static inline void
-hash_netport6_data_netmask(struct hash_netport6_elem *elem, u8 cidr)
-{
- ip6_netmask(&elem->ip, cidr);
- elem->cidr = cidr;
-}
-
-static bool
-hash_netport6_data_list(struct sk_buff *skb,
- const struct hash_netport6_elem *data)
-{
- NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &data->ip);
- NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
- NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
- NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
- return 0;
-
-nla_put_failure:
- return 1;
-}
-
-static bool
-hash_netport6_data_tlist(struct sk_buff *skb,
- const struct hash_netport6_elem *data)
-{
- const struct hash_netport6_telem *e =
- (const struct hash_netport6_telem *)data;
-
- NLA_PUT_IPADDR6(skb, IPSET_ATTR_IP, &e->ip);
- NLA_PUT_NET16(skb, IPSET_ATTR_PORT, data->port);
- NLA_PUT_U8(skb, IPSET_ATTR_CIDR, data->cidr);
- NLA_PUT_U8(skb, IPSET_ATTR_PROTO, data->proto);
- NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
- htonl(ip_set_timeout_get(e->timeout)));
- return 0;
-
-nla_put_failure:
- return 1;
-}
-
-#undef PF
-#undef HOST_MASK
-
-#define PF 6
-#define HOST_MASK 128
-#include "ip_set_ahash.h"
-
-static inline void
-hash_netport6_data_next(struct ip_set_hash *h,
- const struct hash_netport6_elem *d)
-{
- h->next.port = ntohs(d->port);
-}
-
-static int
-hash_netport6_kadt(struct ip_set *set, const struct sk_buff *skb,
- const struct xt_action_param *par,
- enum ipset_adt adt, const struct ip_set_adt_opt *opt)
-{
- const struct ip_set_hash *h = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- struct hash_netport6_elem data = {
- .cidr = h->nets[0].cidr ? h->nets[0].cidr : HOST_MASK
- };
-
- if (data.cidr == 0)
- return -EINVAL;
- if (adt == IPSET_TEST)
- data.cidr = HOST_MASK;
-
- if (!ip_set_get_ip6_port(skb, opt->flags & IPSET_DIM_TWO_SRC,
- &data.port, &data.proto))
- return -EINVAL;
-
- ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &data.ip.in6);
- ip6_netmask(&data.ip, data.cidr);
-
- return adtfn(set, &data, opt_timeout(opt, h), opt->cmdflags);
-}
-
-static int
-hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
- enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
-{
- const struct ip_set_hash *h = set->data;
- ipset_adtfn adtfn = set->variant->adt[adt];
- 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] ||
- !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 (unlikely(tb[IPSET_ATTR_IP_TO]))
- return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
-
- if (tb[IPSET_ATTR_LINENO])
- *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
-
- ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &data.ip);
- if (ret)
- return ret;
-
- if (tb[IPSET_ATTR_CIDR])
- data.cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
- if (!data.cidr)
- return -IPSET_ERR_INVALID_CIDR;
- ip6_netmask(&data.ip, data.cidr);
-
- if (tb[IPSET_ATTR_PORT])
- data.port = nla_get_be16(tb[IPSET_ATTR_PORT]);
- else
- return -IPSET_ERR_PROTOCOL;
-
- 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;
-
- if (!(with_ports || data.proto == IPPROTO_ICMPV6))
- data.port = 0;
-
- if (tb[IPSET_ATTR_TIMEOUT]) {
- if (!with_timeout(h->timeout))
- return -IPSET_ERR_TIMEOUT;
- timeout = ip_set_timeout_uget(tb[IPSET_ATTR_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;
- }
-
- port = ntohs(data.port);
- port_to = ip_set_get_h16(tb[IPSET_ATTR_PORT_TO]);
- if (port > port_to)
- swap(port, port_to);
-
- if (retried)
- port = h->next.port;
- for (; port <= port_to; port++) {
- data.port = htons(port);
- ret = adtfn(set, &data, timeout, flags);
-
- if (ret && !ip_set_eexist(ret, flags))
- return ret;
- else
- ret = 0;
- }
- return ret;
-}
-
-/* Create hash:ip type of sets */
-
-static int
-hash_netport_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
-{
- struct ip_set_hash *h;
- u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM;
- u8 hbits;
-
- if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
- return -IPSET_ERR_INVALID_FAMILY;
-
- 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)))
- return -IPSET_ERR_PROTOCOL;
-
- if (tb[IPSET_ATTR_HASHSIZE]) {
- hashsize = ip_set_get_h32(tb[IPSET_ATTR_HASHSIZE]);
- if (hashsize < IPSET_MIMINAL_HASHSIZE)
- hashsize = IPSET_MIMINAL_HASHSIZE;
- }
-
- if (tb[IPSET_ATTR_MAXELEM])
- maxelem = ip_set_get_h32(tb[IPSET_ATTR_MAXELEM]);
-
- h = kzalloc(sizeof(*h)
- + sizeof(struct ip_set_hash_nets)
- * (set->family == NFPROTO_IPV4 ? 32 : 128), GFP_KERNEL);
- if (!h)
- return -ENOMEM;
-
- h->maxelem = maxelem;
- get_random_bytes(&h->initval, sizeof(h->initval));
- h->timeout = IPSET_NO_TIMEOUT;
-
- hbits = htable_bits(hashsize);
- h->table = ip_set_alloc(
- sizeof(struct htable)
- + jhash_size(hbits) * sizeof(struct hbucket));
- if (!h->table) {
- kfree(h);
- return -ENOMEM;
- }
- h->table->htable_bits = hbits;
-
- set->data = h;
-
- if (tb[IPSET_ATTR_TIMEOUT]) {
- h->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
-
- set->variant = set->family == NFPROTO_IPV4
- ? &hash_netport4_tvariant : &hash_netport6_tvariant;
-
- if (set->family == NFPROTO_IPV4)
- hash_netport4_gc_init(set);
- else
- hash_netport6_gc_init(set);
- } else {
- set->variant = set->family == NFPROTO_IPV4
- ? &hash_netport4_variant : &hash_netport6_variant;
- }
-
- pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
- set->name, jhash_size(h->table->htable_bits),
- h->table->htable_bits, h->maxelem, set->data, h->table);
-
- return 0;
-}
-
-static struct ip_set_type hash_netport_type __read_mostly = {
- .name = "hash:net,port",
- .protocol = IPSET_PROTOCOL,
- .features = IPSET_TYPE_IP | IPSET_TYPE_PORT,
- .dimension = IPSET_DIM_TWO,
- .family = NFPROTO_UNSPEC,
- .revision_min = 0,
- /* 1 SCTP and UDPLITE support added */
- .revision_max = 2, /* Range as input support for IPv4 added */
- .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_IP_TO] = { .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,
-};
-
-static int __init
-hash_netport_init(void)
-{
- return ip_set_type_register(&hash_netport_type);
-}
-
-static void __exit
-hash_netport_fini(void)
-{
- ip_set_type_unregister(&hash_netport_type);
-}
-
-module_init(hash_netport_init);
-module_exit(hash_netport_fini);
+++ /dev/null
-#ifndef __IP_SET_LIST_H
-#define __IP_SET_LIST_H
-
-/* List type specific error codes */
-enum {
- /* Set name to be added/deleted/tested does not exist. */
- IPSET_ERR_NAME = IPSET_ERR_TYPE_SPECIFIC,
- /* list:set type is not permitted to add */
- IPSET_ERR_LOOP,
- /* Missing reference set */
- IPSET_ERR_BEFORE,
- /* Reference set does not exist */
- IPSET_ERR_NAMEREF,
- /* Set is full */
- IPSET_ERR_LIST_FULL,
- /* Reference set is not added to the set */
- IPSET_ERR_REF_EXIST,
-};
-
-#ifdef __KERNEL__
-
-#define IP_SET_LIST_DEFAULT_SIZE 8
-#define IP_SET_LIST_MIN_SIZE 4
-
-#endif /* __KERNEL__ */
-
-#endif /* __IP_SET_LIST_H */
+++ /dev/null
-/* Copyright (C) 2008-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/* Kernel module implementing an IP set type: the list:set type */
-
-#include <linux/module.h>
-#include <linux/ip.h>
-#include <linux/skbuff.h>
-#include <linux/errno.h>
-
-#include "ip_set.h"
-#include "ip_set_timeout.h"
-#include "ip_set_list.h"
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
-MODULE_DESCRIPTION("list:set type of IP sets");
-MODULE_ALIAS("ip_set_list:set");
-
-/* Member elements without and with timeout */
-struct set_elem {
- ip_set_id_t id;
-};
-
-struct set_telem {
- ip_set_id_t id;
- unsigned long timeout;
-};
-
-/* Type structure */
-struct list_set {
- size_t dsize; /* element size */
- u32 size; /* size of set list array */
- u32 timeout; /* timeout value */
- struct timer_list gc; /* garbage collection */
- struct set_elem members[0]; /* the set members */
-};
-
-static inline struct set_elem *
-list_set_elem(const struct list_set *map, u32 id)
-{
- 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 = list_set_telem(map, id);
-
- return ip_set_timeout_test(elem->timeout);
-}
-
-static inline bool
-list_set_expired(const struct list_set *map, u32 id)
-{
- const struct set_telem *elem = list_set_telem(map, id);
-
- return ip_set_timeout_expired(elem->timeout);
-}
-
-/* Set list without and with timeout */
-
-static int
-list_set_kadt(struct ip_set *set, const struct sk_buff *skb,
- const struct xt_action_param *par,
- enum ipset_adt adt, const struct ip_set_adt_opt *opt)
-{
- struct list_set *map = set->data;
- struct set_elem *elem;
- u32 i;
- int ret;
-
- for (i = 0; i < map->size; i++) {
- elem = list_set_elem(map, i);
- if (elem->id == IPSET_INVALID_ID)
- return 0;
- if (with_timeout(map->timeout) && list_set_expired(map, i))
- continue;
- switch (adt) {
- case IPSET_TEST:
- ret = ip_set_test(elem->id, skb, par, opt);
- if (ret > 0)
- return ret;
- break;
- case IPSET_ADD:
- ret = ip_set_add(elem->id, skb, par, opt);
- if (ret == 0)
- return ret;
- break;
- case IPSET_DEL:
- ret = ip_set_del(elem->id, skb, par, opt);
- if (ret == 0)
- return ret;
- break;
- default:
- break;
- }
- }
- return -EINVAL;
-}
-
-static bool
-id_eq(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;
- }
-
- 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)));
- }
-
- return 0;
-}
-
-static void
-list_elem_add(struct list_set *map, u32 i, ip_set_id_t id)
-{
- struct set_elem *e;
-
- for (; i < map->size; i++) {
- e = list_set_elem(map, i);
- swap(e->id, id);
- if (e->id == IPSET_INVALID_ID)
- break;
- }
-}
-
-static void
-list_elem_tadd(struct list_set *map, u32 i, ip_set_id_t id,
- unsigned long timeout)
-{
- struct set_telem *e;
-
- for (; i < map->size; i++) {
- e = list_set_telem(map, i);
- swap(e->id, id);
- swap(e->timeout, timeout);
- if (e->id == IPSET_INVALID_ID)
- break;
- }
-}
-
-static int
-list_set_add(struct list_set *map, u32 i, ip_set_id_t id,
- unsigned long timeout)
-{
- const struct set_elem *e = list_set_elem(map, i);
-
- if (i == map->size - 1 && e->id != IPSET_INVALID_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, ip_set_timeout_set(timeout));
- else
- list_elem_add(map, i, id);
-
- return 0;
-}
-
-static int
-list_set_del(struct list_set *map, u32 i)
-{
- struct set_elem *a = list_set_elem(map, i), *b;
-
- ip_set_put_byindex(a->id);
-
- for (; i < map->size - 1; i++) {
- b = list_set_elem(map, i + 1);
- a->id = b->id;
- if (with_timeout(map->timeout))
- ((struct set_telem *)a)->timeout =
- ((struct set_telem *)b)->timeout;
- a = b;
- if (a->id == IPSET_INVALID_ID)
- break;
- }
- /* Last element */
- a->id = IPSET_INVALID_ID;
- 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, bool retried)
-{
- 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;
- const struct set_elem *elem;
- struct ip_set *s;
- u32 i;
- int ret = 0;
-
- if (unlikely(!tb[IPSET_ATTR_NAME] ||
- !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
- !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS)))
- return -IPSET_ERR_PROTOCOL;
-
- if (tb[IPSET_ATTR_LINENO])
- *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
-
- id = ip_set_get_byname(nla_data(tb[IPSET_ATTR_NAME]), &s);
- if (id == IPSET_INVALID_ID)
- return -IPSET_ERR_NAME;
- /* "Loop detection" */
- if (s->type->features & IPSET_TYPE_NAME) {
- ret = -IPSET_ERR_LOOP;
- goto finish;
- }
-
- if (tb[IPSET_ATTR_CADT_FLAGS]) {
- u32 f = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]);
- before = f & IPSET_FLAG_BEFORE;
- }
-
- if (before && !tb[IPSET_ATTR_NAMEREF]) {
- ret = -IPSET_ERR_BEFORE;
- goto finish;
- }
-
- if (tb[IPSET_ATTR_NAMEREF]) {
- refid = ip_set_get_byname(nla_data(tb[IPSET_ATTR_NAMEREF]),
- &s);
- if (refid == IPSET_INVALID_ID) {
- ret = -IPSET_ERR_NAMEREF;
- goto finish;
- }
- if (!before)
- before = -1;
- }
- if (tb[IPSET_ATTR_TIMEOUT]) {
- if (!with_timeout) {
- ret = -IPSET_ERR_TIMEOUT;
- goto finish;
- }
- timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
- }
- if (with_timeout && adt != IPSET_TEST)
- cleanup_entries(map);
-
- switch (adt) {
- case IPSET_TEST:
- for (i = 0; i < map->size && !ret; i++) {
- elem = list_set_elem(map, i);
- if (elem->id == IPSET_INVALID_ID ||
- (before != 0 && i + 1 >= map->size))
- break;
- else if (with_timeout && list_set_expired(map, i))
- continue;
- else if (before > 0 && elem->id == id)
- ret = id_eq_timeout(map, i + 1, refid);
- else if (before < 0 && elem->id == refid)
- 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; i++) {
- elem = list_set_elem(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;
- }
- }
- ret = -IPSET_ERR_LIST_FULL;
- for (i = 0; i < map->size && ret == -IPSET_ERR_LIST_FULL; i++) {
- elem = list_set_elem(map, i);
- if (elem->id == IPSET_INVALID_ID)
- ret = before != 0 ? -IPSET_ERR_REF_EXIST
- : list_set_add(map, i, id, timeout);
- else if (elem->id != refid)
- continue;
- 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);
- }
- break;
- case IPSET_DEL:
- ret = -IPSET_ERR_EXIST;
- for (i = 0; i < map->size && ret == -IPSET_ERR_EXIST; i++) {
- elem = list_set_elem(map, i);
- if (elem->id == IPSET_INVALID_ID) {
- ret = before != 0 ? -IPSET_ERR_REF_EXIST
- : -IPSET_ERR_EXIST;
- break;
- } 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:
- break;
- }
-
-finish:
- if (refid != IPSET_INVALID_ID)
- ip_set_put_byindex(refid);
- if (adt != IPSET_ADD || ret)
- ip_set_put_byindex(id);
-
- return ip_set_eexist(ret, flags) ? 0 : ret;
-}
-
-static void
-list_set_flush(struct ip_set *set)
-{
- struct list_set *map = set->data;
- struct set_elem *elem;
- u32 i;
-
- for (i = 0; i < map->size; i++) {
- elem = list_set_elem(map, i);
- if (elem->id != IPSET_INVALID_ID) {
- ip_set_put_byindex(elem->id);
- elem->id = IPSET_INVALID_ID;
- }
- }
-}
-
-static void
-list_set_destroy(struct ip_set *set)
-{
- struct list_set *map = set->data;
-
- if (with_timeout(map->timeout))
- del_timer_sync(&map->gc);
- list_set_flush(set);
- kfree(map);
-
- set->data = NULL;
-}
-
-static int
-list_set_head(struct ip_set *set, struct sk_buff *skb)
-{
- const struct list_set *map = set->data;
- struct nlattr *nested;
-
- nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
- if (!nested)
- goto nla_put_failure;
- 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(set->ref - 1));
- NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
- htonl(sizeof(*map) + map->size * map->dsize));
- ipset_nest_end(skb, nested);
-
- return 0;
-nla_put_failure:
- return -EMSGSIZE;
-}
-
-static int
-list_set_list(const struct ip_set *set,
- struct sk_buff *skb, struct netlink_callback *cb)
-{
- const struct list_set *map = set->data;
- struct nlattr *atd, *nested;
- u32 i, first = cb->args[2];
- const struct set_elem *e;
-
- atd = ipset_nest_start(skb, IPSET_ATTR_ADT);
- if (!atd)
- return -EMSGSIZE;
- for (; cb->args[2] < map->size; cb->args[2]++) {
- i = cb->args[2];
- e = list_set_elem(map, i);
- if (e->id == IPSET_INVALID_ID)
- goto finish;
- if (with_timeout(map->timeout) && list_set_expired(map, i))
- continue;
- nested = ipset_nest_start(skb, IPSET_ATTR_DATA);
- if (!nested) {
- if (i == first) {
- nla_nest_cancel(skb, atd);
- return -EMSGSIZE;
- } else
- goto nla_put_failure;
- }
- NLA_PUT_STRING(skb, IPSET_ATTR_NAME,
- ip_set_name_byindex(e->id));
- if (with_timeout(map->timeout)) {
- const struct set_telem *te =
- (const struct set_telem *) e;
- NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT,
- htonl(ip_set_timeout_get(te->timeout)));
- }
- ipset_nest_end(skb, nested);
- }
-finish:
- 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(i == first)) {
- cb->args[2] = 0;
- return -EMSGSIZE;
- }
- return 0;
-}
-
-static bool
-list_set_same_set(const struct ip_set *a, const struct ip_set *b)
-{
- const struct list_set *x = a->data;
- const struct list_set *y = b->data;
-
- return x->size == y->size &&
- x->timeout == y->timeout;
-}
-
-static const struct ip_set_type_variant list_set = {
- .kadt = list_set_kadt,
- .uadt = list_set_uadt,
- .destroy = list_set_destroy,
- .flush = list_set_flush,
- .head = list_set_head,
- .list = list_set_list,
- .same_set = list_set_same_set,
-};
-
-static void
-list_set_gc(unsigned long ul_set)
-{
- struct ip_set *set = (struct ip_set *) ul_set;
- struct list_set *map = set->data;
-
- 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);
-}
-
-static void
-list_set_gc_init(struct ip_set *set)
-{
- struct list_set *map = set->data;
-
- init_timer(&map->gc);
- map->gc.data = (unsigned long) set;
- map->gc.function = list_set_gc;
- map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
- add_timer(&map->gc);
-}
-
-/* Create list:set type of sets */
-
-static bool
-init_list_set(struct ip_set *set, u32 size, size_t dsize,
- unsigned long timeout)
-{
- struct list_set *map;
- struct set_elem *e;
- u32 i;
-
- map = kzalloc(sizeof(*map) + size * dsize, GFP_KERNEL);
- if (!map)
- return false;
-
- map->size = size;
- map->dsize = dsize;
- map->timeout = timeout;
- set->data = map;
-
- for (i = 0; i < size; i++) {
- e = list_set_elem(map, i);
- e->id = IPSET_INVALID_ID;
- }
-
- return true;
-}
-
-static int
-list_set_create(struct ip_set *set, struct nlattr *tb[], u32 flags)
-{
- u32 size = IP_SET_LIST_DEFAULT_SIZE;
-
- if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_SIZE) ||
- !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT)))
- return -IPSET_ERR_PROTOCOL;
-
- if (tb[IPSET_ATTR_SIZE])
- size = ip_set_get_h32(tb[IPSET_ATTR_SIZE]);
- if (size < IP_SET_LIST_MIN_SIZE)
- size = IP_SET_LIST_MIN_SIZE;
-
- if (tb[IPSET_ATTR_TIMEOUT]) {
- if (!init_list_set(set, size, sizeof(struct set_telem),
- ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT])))
- return -ENOMEM;
-
- list_set_gc_init(set);
- } else {
- if (!init_list_set(set, size, sizeof(struct set_elem),
- IPSET_NO_TIMEOUT))
- return -ENOMEM;
- }
- set->variant = &list_set;
- return 0;
-}
-
-static struct ip_set_type list_set_type __read_mostly = {
- .name = "list:set",
- .protocol = IPSET_PROTOCOL,
- .features = IPSET_TYPE_NAME | IPSET_DUMP_LAST,
- .dimension = IPSET_DIM_ONE,
- .family = NFPROTO_UNSPEC,
- .revision_min = 0,
- .revision_max = 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,
-};
-
-static int __init
-list_set_init(void)
-{
- return ip_set_type_register(&list_set_type);
-}
-
-static void __exit
-list_set_fini(void)
-{
- ip_set_type_unregister(&list_set_type);
-}
-
-module_init(list_set_init);
-module_exit(list_set_fini);
+++ /dev/null
-#ifndef _IP_SET_TIMEOUT_H
-#define _IP_SET_TIMEOUT_H
-
-/* Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifdef __KERNEL__
-
-/* How often should the gc be run by default */
-#define IPSET_GC_TIME (3 * 60)
-
-/* Timeout period depending on the timeout value of the given set */
-#define IPSET_GC_PERIOD(timeout) \
- ((timeout/3) ? min_t(u32, (timeout)/3, IPSET_GC_TIME) : 1)
-
-/* Set is defined without timeout support: timeout value may be 0 */
-#define IPSET_NO_TIMEOUT UINT_MAX
-
-#define with_timeout(timeout) ((timeout) != IPSET_NO_TIMEOUT)
-
-#define opt_timeout(opt, map) \
- (with_timeout((opt)->timeout) ? (opt)->timeout : (map)->timeout)
-
-static inline unsigned int
-ip_set_timeout_uget(struct nlattr *tb)
-{
- unsigned int timeout = ip_set_get_h32(tb);
-
- /* Userspace supplied TIMEOUT parameter: adjust crazy size */
- return timeout == IPSET_NO_TIMEOUT ? IPSET_NO_TIMEOUT - 1 : timeout;
-}
-
-#ifdef IP_SET_BITMAP_TIMEOUT
-
-/* Bitmap specific timeout constants and macros for the entries */
-
-/* Bitmap entry is unset */
-#define IPSET_ELEM_UNSET 0
-/* Bitmap entry is set with no timeout value */
-#define IPSET_ELEM_PERMANENT (UINT_MAX/2)
-
-static inline bool
-ip_set_timeout_test(unsigned long timeout)
-{
- return timeout != IPSET_ELEM_UNSET &&
- (timeout == IPSET_ELEM_PERMANENT ||
- time_is_after_jiffies(timeout));
-}
-
-static inline bool
-ip_set_timeout_expired(unsigned long timeout)
-{
- return timeout != IPSET_ELEM_UNSET &&
- timeout != IPSET_ELEM_PERMANENT &&
- time_is_before_jiffies(timeout);
-}
-
-static inline unsigned long
-ip_set_timeout_set(u32 timeout)
-{
- unsigned long t;
-
- if (!timeout)
- return IPSET_ELEM_PERMANENT;
-
- t = msecs_to_jiffies(timeout * 1000) + jiffies;
- if (t == IPSET_ELEM_UNSET || t == IPSET_ELEM_PERMANENT)
- /* Bingo! */
- t++;
-
- return t;
-}
-
-static inline u32
-ip_set_timeout_get(unsigned long timeout)
-{
- return timeout == IPSET_ELEM_PERMANENT ? 0 :
- jiffies_to_msecs(timeout - jiffies)/1000;
-}
-
-#else
-
-/* Hash specific timeout constants and macros for the entries */
-
-/* Hash entry is set with no timeout value */
-#define IPSET_ELEM_PERMANENT 0
-
-static inline bool
-ip_set_timeout_test(unsigned long timeout)
-{
- return timeout == IPSET_ELEM_PERMANENT ||
- time_is_after_jiffies(timeout);
-}
-
-static inline bool
-ip_set_timeout_expired(unsigned long timeout)
-{
- return timeout != IPSET_ELEM_PERMANENT &&
- time_is_before_jiffies(timeout);
-}
-
-static inline unsigned long
-ip_set_timeout_set(u32 timeout)
-{
- unsigned long t;
-
- if (!timeout)
- return IPSET_ELEM_PERMANENT;
-
- t = msecs_to_jiffies(timeout * 1000) + jiffies;
- if (t == IPSET_ELEM_PERMANENT)
- /* Bingo! :-) */
- t++;
-
- return t;
-}
-
-static inline u32
-ip_set_timeout_get(unsigned long timeout)
-{
- return timeout == IPSET_ELEM_PERMANENT ? 0 :
- jiffies_to_msecs(timeout - jiffies)/1000;
-}
-#endif /* ! IP_SET_BITMAP_TIMEOUT */
-
-#endif /* __KERNEL__ */
-
-#endif /* _IP_SET_TIMEOUT_H */
+++ /dev/null
-#ifndef _LINUX_JHASH_H
-#define _LINUX_JHASH_H
-
-/* jhash.h: Jenkins hash support.
- *
- * Copyright (C) 2006. Bob Jenkins (bob_jenkins@burtleburtle.net)
- *
- * http://burtleburtle.net/bob/hash/
- *
- * These are the credits from Bob's sources:
- *
- * lookup3.c, by Bob Jenkins, May 2006, Public Domain.
- *
- * These are functions for producing 32-bit hashes for hash table lookup.
- * hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final()
- * are externally useful functions. Routines to test the hash are included
- * if SELF_TEST is defined. You can use this free for any purpose. It's in
- * the public domain. It has no warranty.
- *
- * Copyright (C) 2009-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * I've modified Bob's hash to be useful in the Linux kernel, and
- * any bugs present are my fault.
- * Jozsef
- */
-#include <linux/bitops.h>
-#include <linux/unaligned/packed_struct.h>
-
-/* Best hash sizes are of power of two */
-#define jhash_size(n) ((u32)1<<(n))
-/* Mask the hash value, i.e (value & jhash_mask(n)) instead of (value % n) */
-#define jhash_mask(n) (jhash_size(n)-1)
-
-/* __jhash_mix -- mix 3 32-bit values reversibly. */
-#define __jhash_mix(a, b, c) \
-{ \
- a -= c; a ^= rol32(c, 4); c += b; \
- b -= a; b ^= rol32(a, 6); a += c; \
- c -= b; c ^= rol32(b, 8); b += a; \
- a -= c; a ^= rol32(c, 16); c += b; \
- b -= a; b ^= rol32(a, 19); a += c; \
- c -= b; c ^= rol32(b, 4); b += a; \
-}
-
-/* __jhash_final - final mixing of 3 32-bit values (a,b,c) into c */
-#define __jhash_final(a, b, c) \
-{ \
- c ^= b; c -= rol32(b, 14); \
- a ^= c; a -= rol32(c, 11); \
- b ^= a; b -= rol32(a, 25); \
- c ^= b; c -= rol32(b, 16); \
- a ^= c; a -= rol32(c, 4); \
- b ^= a; b -= rol32(a, 14); \
- c ^= b; c -= rol32(b, 24); \
-}
-
-/* An arbitrary initial parameter */
-#define JHASH_INITVAL 0xdeadbeef
-
-/* jhash - hash an arbitrary key
- * @k: sequence of bytes as key
- * @length: the length of the key
- * @initval: the previous hash, or an arbitray value
- *
- * The generic version, hashes an arbitrary sequence of bytes.
- * No alignment or length assumptions are made about the input key.
- *
- * Returns the hash value of the key. The result depends on endianness.
- */
-static inline u32 jhash(const void *key, u32 length, u32 initval)
-{
- u32 a, b, c;
- const u8 *k = key;
-
- /* Set up the internal state */
- a = b = c = JHASH_INITVAL + length + initval;
-
- /* All but the last block: affect some 32 bits of (a,b,c) */
- while (length > 12) {
- a += __get_unaligned_cpu32(k);
- b += __get_unaligned_cpu32(k + 4);
- c += __get_unaligned_cpu32(k + 8);
- __jhash_mix(a, b, c);
- length -= 12;
- k += 12;
- }
- /* Last block: affect all 32 bits of (c) */
- /* All the case statements fall through */
- switch (length) {
- case 12: c += (u32)k[11]<<24;
- case 11: c += (u32)k[10]<<16;
- case 10: c += (u32)k[9]<<8;
- case 9: c += k[8];
- case 8: b += (u32)k[7]<<24;
- case 7: b += (u32)k[6]<<16;
- case 6: b += (u32)k[5]<<8;
- case 5: b += k[4];
- case 4: a += (u32)k[3]<<24;
- case 3: a += (u32)k[2]<<16;
- case 2: a += (u32)k[1]<<8;
- case 1: a += k[0];
- __jhash_final(a, b, c);
- case 0: /* Nothing left to add */
- break;
- }
-
- return c;
-}
-
-/* jhash2 - hash an array of u32's
- * @k: the key which must be an array of u32's
- * @length: the number of u32's in the key
- * @initval: the previous hash, or an arbitray value
- *
- * Returns the hash value of the key.
- */
-static inline u32 jhash2(const u32 *k, u32 length, u32 initval)
-{
- u32 a, b, c;
-
- /* Set up the internal state */
- a = b = c = JHASH_INITVAL + (length<<2) + initval;
-
- /* Handle most of the key */
- while (length > 3) {
- a += k[0];
- b += k[1];
- c += k[2];
- __jhash_mix(a, b, c);
- length -= 3;
- k += 3;
- }
-
- /* Handle the last 3 u32's: all the case statements fall through */
- switch (length) {
- case 3: c += k[2];
- case 2: b += k[1];
- case 1: a += k[0];
- __jhash_final(a, b, c);
- case 0: /* Nothing left to add */
- break;
- }
-
- return c;
-}
-
-/* jhash_3words - hash exactly 3, 2 or 1 word(s) */
-static inline u32 jhash_3words(u32 a, u32 b, u32 c, u32 initval)
-{
- a += JHASH_INITVAL;
- b += JHASH_INITVAL;
- c += initval;
-
- __jhash_final(a, b, c);
-
- return c;
-}
-
-static inline u32 jhash_2words(u32 a, u32 b, u32 initval)
-{
- return jhash_3words(a, b, 0, initval);
-}
-
-static inline u32 jhash_1word(u32 a, u32 initval)
-{
- return jhash_3words(a, 0, 0, initval);
-}
-
-#endif /* _LINUX_JHASH_H */
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <assert.h> /* assert */
-#include <arpa/inet.h> /* ntoh* */
-#include <net/ethernet.h> /* ETH_ALEN */
-#include <net/if.h> /* IFNAMSIZ */
-#include <stdlib.h> /* malloc, free */
-#include <string.h> /* memset */
-
-#include <libipset/linux_ip_set.h> /* IPSET_MAXNAMELEN */
-#include <libipset/debug.h> /* D() */
-#include <libipset/types.h> /* struct ipset_type */
-#include <libipset/utils.h> /* inXcpy */
-#include <libipset/data.h> /* prototypes */
-
-/* Internal data structure to hold
- * a) input data entered by the user or
- * b) data received from kernel
- *
- * We always store the data in host order, *except* IP addresses.
- */
-
-struct ipset_data {
- /* Option bits: which fields are set */
- uint64_t bits;
- /* Option bits: which options are ignored */
- uint64_t ignored;
- /* Setname */
- char setname[IPSET_MAXNAMELEN];
- /* Set type */
- const struct ipset_type *type;
- /* Common CADT options */
- uint8_t cidr;
- uint8_t family;
- uint32_t flags; /* command level flags */
- uint32_t cadt_flags; /* data level flags */
- uint32_t timeout;
- union nf_inet_addr ip;
- union nf_inet_addr ip_to;
- uint16_t port;
- uint16_t port_to;
- union {
- /* RENAME/SWAP */
- char setname2[IPSET_MAXNAMELEN];
- /* CREATE/LIST/SAVE */
- struct {
- uint8_t probes;
- uint8_t resize;
- uint8_t netmask;
- uint32_t hashsize;
- uint32_t maxelem;
- uint32_t gc;
- uint32_t size;
- /* Filled out by kernel */
- uint32_t references;
- uint32_t elements;
- uint32_t memsize;
- char typename[IPSET_MAXNAMELEN];
- uint8_t revision_min;
- uint8_t revision;
- } create;
- /* ADT/LIST/SAVE */
- struct {
- union nf_inet_addr ip2;
- union nf_inet_addr ip2_to;
- uint8_t cidr2;
- uint8_t proto;
- char ether[ETH_ALEN];
- char name[IPSET_MAXNAMELEN];
- char nameref[IPSET_MAXNAMELEN];
- char iface[IFNAMSIZ];
- } adt;
- };
-};
-
-static void
-copy_addr(uint8_t family, union nf_inet_addr *ip, const void *value)
-{
- if (family == NFPROTO_IPV4)
- in4cpy(&ip->in, value);
- else
- in6cpy(&ip->in6, value);
-}
-
-/**
- * ipset_strlcpy - copy the string from src to dst
- * @dst: the target string buffer
- * @src: the source string buffer
- * @len: the length of bytes to copy, including the terminating null byte.
- *
- * Copy the string from src to destination, but at most len bytes are
- * copied. The target is unconditionally terminated by the null byte.
- */
-void
-ipset_strlcpy(char *dst, const char *src, size_t len)
-{
- assert(dst);
- assert(src);
-
- strncpy(dst, src, len);
- dst[len - 1] = '\0';
-}
-
-/**
- * ipset_data_flags_test - test option bits in the data blob
- * @data: data blob
- * @flags: the option flags to test
- *
- * Returns true if the options are already set in the data blob.
- */
-bool
-ipset_data_flags_test(const struct ipset_data *data, uint64_t flags)
-{
- assert(data);
- return !!(data->bits & flags);
-}
-
-/**
- * ipset_data_flags_set - set option bits in the data blob
- * @data: data blob
- * @flags: the option flags to set
- *
- * The function sets the flags in the data blob so that
- * the corresponding fields are regarded as if filled with proper data.
- */
-void
-ipset_data_flags_set(struct ipset_data *data, uint64_t flags)
-{
- assert(data);
- data->bits |= flags;
-}
-
-/**
- * ipset_data_flags_unset - unset option bits in the data blob
- * @data: data blob
- * @flags: the option flags to unset
- *
- * The function unsets the flags in the data blob.
- * This is the quick way to clear specific fields.
- */
-void
-ipset_data_flags_unset(struct ipset_data *data, uint64_t flags)
-{
- assert(data);
- data->bits &= ~flags;
-}
-
-#define flag_type_attr(data, opt, flag) \
-do { \
- data->flags |= flag; \
- opt = IPSET_OPT_FLAGS; \
-} while (0)
-
-#define cadt_flag_type_attr(data, opt, flag) \
-do { \
- data->cadt_flags |= flag; \
- opt = IPSET_OPT_CADT_FLAGS; \
-} while (0)
-
-/**
- * ipset_data_ignored - test and set ignored bits in the data blob
- * @data: data blob
- * @flags: the option flag to be ignored
- *
- * Returns true if the option was not already ignored.
- */
-bool
-ipset_data_ignored(struct ipset_data *data, enum ipset_opt opt)
-{
- bool ignored;
- assert(data);
-
- ignored = data->ignored & IPSET_FLAG(opt);
- data->ignored |= IPSET_FLAG(opt);
-
- return ignored;
-}
-
-/**
- * ipset_data_set - put data into the data blob
- * @data: data blob
- * @opt: the option kind of the data
- * @value: the value of the data
- *
- * Put a given kind of data into the data blob and mark the
- * option kind as already set in the blob.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_data_set(struct ipset_data *data, enum ipset_opt opt, const void *value)
-{
- assert(data);
- assert(opt != IPSET_OPT_NONE);
- assert(value);
-
- switch (opt) {
- /* Common ones */
- case IPSET_SETNAME:
- ipset_strlcpy(data->setname, value, IPSET_MAXNAMELEN);
- break;
- case IPSET_OPT_TYPE:
- data->type = value;
- break;
- case IPSET_OPT_FAMILY:
- data->family = *(const uint8_t *) value;
- D("family set to %u", data->family);
- break;
- /* CADT options */
- case IPSET_OPT_IP:
- if (!(data->family == NFPROTO_IPV4 || data->family == NFPROTO_IPV6))
- return -1;
- copy_addr(data->family, &data->ip, value);
- break;
- case IPSET_OPT_IP_TO:
- if (!(data->family == NFPROTO_IPV4 || data->family == NFPROTO_IPV6))
- return -1;
- copy_addr(data->family, &data->ip_to, value);
- break;
- case IPSET_OPT_CIDR:
- data->cidr = *(const uint8_t *) value;
- break;
- case IPSET_OPT_PORT:
- data->port = *(const uint16_t *) value;
- break;
- case IPSET_OPT_PORT_TO:
- data->port_to = *(const uint16_t *) value;
- break;
- case IPSET_OPT_TIMEOUT:
- data->timeout = *(const uint32_t *) value;
- break;
- /* Create-specific options */
- case IPSET_OPT_GC:
- data->create.gc = *(const uint32_t *) value;
- break;
- case IPSET_OPT_HASHSIZE:
- data->create.hashsize = *(const uint32_t *) value;
- break;
- case IPSET_OPT_MAXELEM:
- data->create.maxelem = *(const uint32_t *) value;
- break;
- case IPSET_OPT_NETMASK:
- data->create.netmask = *(const uint8_t *) value;
- break;
- case IPSET_OPT_PROBES:
- data->create.probes = *(const uint8_t *) value;
- break;
- case IPSET_OPT_RESIZE:
- data->create.resize = *(const uint8_t *) value;
- break;
- case IPSET_OPT_SIZE:
- data->create.size = *(const uint32_t *) value;
- break;
- /* Create-specific options, filled out by the kernel */
- case IPSET_OPT_ELEMENTS:
- data->create.elements = *(const uint32_t *) value;
- break;
- case IPSET_OPT_REFERENCES:
- data->create.references = *(const uint32_t *) value;
- break;
- case IPSET_OPT_MEMSIZE:
- data->create.memsize = *(const uint32_t *) value;
- break;
- /* Create-specific options, type */
- case IPSET_OPT_TYPENAME:
- ipset_strlcpy(data->create.typename, value,
- IPSET_MAXNAMELEN);
- break;
- case IPSET_OPT_REVISION:
- data->create.revision = *(const uint8_t *) value;
- break;
- case IPSET_OPT_REVISION_MIN:
- data->create.revision_min = *(const uint8_t *) value;
- break;
- /* ADT-specific options */
- case IPSET_OPT_ETHER:
- memcpy(data->adt.ether, value, ETH_ALEN);
- break;
- case IPSET_OPT_NAME:
- ipset_strlcpy(data->adt.name, value, IPSET_MAXNAMELEN);
- break;
- case IPSET_OPT_NAMEREF:
- ipset_strlcpy(data->adt.nameref, value, IPSET_MAXNAMELEN);
- break;
- case IPSET_OPT_IP2:
- if (!(data->family == NFPROTO_IPV4 || data->family == NFPROTO_IPV6))
- return -1;
- copy_addr(data->family, &data->adt.ip2, value);
- break;
- case IPSET_OPT_IP2_TO:
- if (!(data->family == NFPROTO_IPV4 || data->family == NFPROTO_IPV6))
- return -1;
- copy_addr(data->family, &data->adt.ip2_to, value);
- break;
- case IPSET_OPT_CIDR2:
- data->adt.cidr2 = *(const uint8_t *) value;
- break;
- case IPSET_OPT_PROTO:
- data->adt.proto = *(const uint8_t *) value;
- break;
- case IPSET_OPT_IFACE:
- ipset_strlcpy(data->adt.iface, value, IFNAMSIZ);
- break;
- /* Swap/rename */
- case IPSET_OPT_SETNAME2:
- ipset_strlcpy(data->setname2, value, IPSET_MAXNAMELEN);
- break;
- /* flags */
- case IPSET_OPT_EXIST:
- flag_type_attr(data, opt, IPSET_FLAG_EXIST);
- break;
- case IPSET_OPT_BEFORE:
- cadt_flag_type_attr(data, opt, IPSET_FLAG_BEFORE);
- break;
- case IPSET_OPT_PHYSDEV:
- cadt_flag_type_attr(data, opt, IPSET_FLAG_PHYSDEV);
- break;
- case IPSET_OPT_FLAGS:
- data->flags = *(const uint32_t *)value;
- break;
- case IPSET_OPT_CADT_FLAGS:
- data->cadt_flags = *(const uint32_t *)value;
- break;
- default:
- return -1;
- };
-
- ipset_data_flags_set(data, IPSET_FLAG(opt));
- return 0;
-}
-
-/**
- * ipset_data_get - get data from the data blob
- * @data: data blob
- * @opt: option kind of the requested data
- *
- * Returns the pointer to the requested kind of data from the data blob
- * if it is set. If the option kind is not set or is an unkown type,
- * NULL is returned.
- */
-const void *
-ipset_data_get(const struct ipset_data *data, enum ipset_opt opt)
-{
- assert(data);
- assert(opt != IPSET_OPT_NONE);
-
- if (!(opt == IPSET_OPT_TYPENAME || ipset_data_test(data, opt)))
- return NULL;
-
- switch (opt) {
- /* Common ones */
- case IPSET_SETNAME:
- return data->setname;
- case IPSET_OPT_TYPE:
- return data->type;
- case IPSET_OPT_TYPENAME:
- if (ipset_data_test(data, IPSET_OPT_TYPE))
- return data->type->name;
- else if (ipset_data_test(data, IPSET_OPT_TYPENAME))
- return data->create.typename;
- return NULL;
- case IPSET_OPT_FAMILY:
- return &data->family;
- /* CADT options */
- case IPSET_OPT_IP:
- return &data->ip;
- case IPSET_OPT_IP_TO:
- return &data->ip_to;
- case IPSET_OPT_CIDR:
- return &data->cidr;
- case IPSET_OPT_PORT:
- return &data->port;
- case IPSET_OPT_PORT_TO:
- return &data->port_to;
- case IPSET_OPT_TIMEOUT:
- return &data->timeout;
- /* Create-specific options */
- case IPSET_OPT_GC:
- return &data->create.gc;
- case IPSET_OPT_HASHSIZE:
- return &data->create.hashsize;
- case IPSET_OPT_MAXELEM:
- return &data->create.maxelem;
- case IPSET_OPT_NETMASK:
- return &data->create.netmask;
- case IPSET_OPT_PROBES:
- return &data->create.probes;
- case IPSET_OPT_RESIZE:
- return &data->create.resize;
- case IPSET_OPT_SIZE:
- return &data->create.size;
- /* Create-specific options, filled out by the kernel */
- case IPSET_OPT_ELEMENTS:
- return &data->create.elements;
- case IPSET_OPT_REFERENCES:
- return &data->create.references;
- case IPSET_OPT_MEMSIZE:
- return &data->create.memsize;
- /* Create-specific options, TYPE */
- case IPSET_OPT_REVISION:
- return &data->create.revision;
- case IPSET_OPT_REVISION_MIN:
- return &data->create.revision_min;
- /* ADT-specific options */
- case IPSET_OPT_ETHER:
- return data->adt.ether;
- case IPSET_OPT_NAME:
- return data->adt.name;
- case IPSET_OPT_NAMEREF:
- return data->adt.nameref;
- case IPSET_OPT_IP2:
- return &data->adt.ip2;
- case IPSET_OPT_IP2_TO:
- return &data->adt.ip2_to;
- case IPSET_OPT_CIDR2:
- return &data->adt.cidr2;
- case IPSET_OPT_PROTO:
- return &data->adt.proto;
- case IPSET_OPT_IFACE:
- return &data->adt.iface;
- /* Swap/rename */
- case IPSET_OPT_SETNAME2:
- return data->setname2;
- /* flags */
- case IPSET_OPT_FLAGS:
- case IPSET_OPT_EXIST:
- return &data->flags;
- case IPSET_OPT_CADT_FLAGS:
- case IPSET_OPT_BEFORE:
- case IPSET_OPT_PHYSDEV:
- return &data->cadt_flags;
- default:
- return NULL;
- }
-}
-
-/**
- * ipset_data_sizeof - calculates the size of the data type
- * @opt: option kind of the data
- * @family: INET family
- *
- * Returns the size required to store the given data type.
- */
-size_t
-ipset_data_sizeof(enum ipset_opt opt, uint8_t family)
-{
- assert(opt != IPSET_OPT_NONE);
-
- switch (opt) {
- case IPSET_OPT_IP:
- case IPSET_OPT_IP_TO:
- case IPSET_OPT_IP2:
- case IPSET_OPT_IP2_TO:
- return family == NFPROTO_IPV4 ? sizeof(uint32_t)
- : sizeof(struct in6_addr);
- case IPSET_OPT_PORT:
- case IPSET_OPT_PORT_TO:
- return sizeof(uint16_t);
- case IPSET_SETNAME:
- case IPSET_OPT_NAME:
- case IPSET_OPT_NAMEREF:
- return IPSET_MAXNAMELEN;
- case IPSET_OPT_TIMEOUT:
- case IPSET_OPT_GC:
- case IPSET_OPT_HASHSIZE:
- case IPSET_OPT_MAXELEM:
- case IPSET_OPT_SIZE:
- case IPSET_OPT_ELEMENTS:
- case IPSET_OPT_REFERENCES:
- case IPSET_OPT_MEMSIZE:
- return sizeof(uint32_t);
- case IPSET_OPT_CIDR:
- case IPSET_OPT_CIDR2:
- case IPSET_OPT_NETMASK:
- case IPSET_OPT_PROBES:
- case IPSET_OPT_RESIZE:
- case IPSET_OPT_PROTO:
- return sizeof(uint8_t);
- case IPSET_OPT_ETHER:
- return ETH_ALEN;
- /* Flags doesn't counted once :-( */
- case IPSET_OPT_BEFORE:
- case IPSET_OPT_PHYSDEV:
- return sizeof(uint32_t);
- default:
- return 0;
- };
-}
-
-/**
- * ipset_setname - return the name of the set from the data blob
- * @data: data blob
- *
- * Return the name of the set from the data blob or NULL if the
- * name not set yet.
- */
-const char *
-ipset_data_setname(const struct ipset_data *data)
-{
- assert(data);
- return ipset_data_test(data, IPSET_SETNAME) ? data->setname : NULL;
-}
-
-/**
- * ipset_family - return the INET family of the set from the data blob
- * @data: data blob
- *
- * Return the INET family supported by the set from the data blob.
- * If the family is not set yet, NFPROTO_UNSPEC is returned.
- */
-uint8_t
-ipset_data_family(const struct ipset_data *data)
-{
- assert(data);
- return ipset_data_test(data, IPSET_OPT_FAMILY)
- ? data->family : NFPROTO_UNSPEC;
-}
-
-/**
- * ipset_data_cidr - return the value of IPSET_OPT_CIDR
- * @data: data blob
- *
- * Return the value of IPSET_OPT_CIDR stored in the data blob.
- * If it is not set, then the returned value corresponds to
- * the default one according to the family type or zero.
- */
-uint8_t
-ipset_data_cidr(const struct ipset_data *data)
-{
- assert(data);
- return ipset_data_test(data, IPSET_OPT_CIDR) ? data->cidr :
- data->family == NFPROTO_IPV4 ? 32 :
- data->family == NFPROTO_IPV6 ? 128 : 0;
-}
-
-/**
- * ipset_flags - return which fields are set in the data blob
- * @data: data blob
- *
- * Returns the value of the bit field which elements are set.
- */
-uint64_t
-ipset_data_flags(const struct ipset_data *data)
-{
- assert(data);
- return data->bits;
-}
-
-/**
- * ipset_data_reset - reset the data blob to unset
- * @data: data blob
- *
- * Resets the data blob to the unset state for every field.
- */
-void
-ipset_data_reset(struct ipset_data *data)
-{
- assert(data);
- memset(data, 0, sizeof(*data));
-}
-
-/**
- * ipset_data_init - create a new data blob
- *
- * Return the new data blob initialized to empty. In case of
- * an error, NULL is retured.
- */
-struct ipset_data *
-ipset_data_init(void)
-{
- return calloc(1, sizeof(struct ipset_data));
-}
-
-/**
- * ipset_data_fini - release a data blob created by ipset_data_init
- *
- * Release the data blob created by ipset_data_init previously.
- */
-void
-ipset_data_fini(struct ipset_data *data)
-{
- assert(data);
- free(data);
-}
+++ /dev/null
-/* Copyright 2011 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <arpa/inet.h> /* inet_ntop */
-#include <libmnl/libmnl.h> /* libmnl backend */
-
-struct ipset_attrname {
- const char *name;
-};
-
-static const struct ipset_attrname cmdattr2name[] = {
- [IPSET_ATTR_PROTOCOL] = { .name = "PROTOCOL" },
- [IPSET_ATTR_SETNAME] = { .name = "SETNAME" },
- [IPSET_ATTR_TYPENAME] = { .name = "TYPENAME" },
- [IPSET_ATTR_REVISION] = { .name = "REVISION" },
- [IPSET_ATTR_FAMILY] = { .name = "FAMILY" },
- [IPSET_ATTR_FLAGS] = { .name = "FLAGS" },
- [IPSET_ATTR_DATA] = { .name = "DATA" },
- [IPSET_ATTR_ADT] = { .name = "ADT" },
- [IPSET_ATTR_LINENO] = { .name = "LINENO" },
- [IPSET_ATTR_PROTOCOL_MIN] = { .name = "PROTO_MIN" },
-};
-
-static const struct ipset_attrname createattr2name[] = {
- [IPSET_ATTR_IP] = { .name = "IP" },
- [IPSET_ATTR_IP_TO] = { .name = "IP_TO" },
- [IPSET_ATTR_CIDR] = { .name = "CIDR" },
- [IPSET_ATTR_PORT] = { .name = "PORT" },
- [IPSET_ATTR_PORT_TO] = { .name = "PORT_TO" },
- [IPSET_ATTR_TIMEOUT] = { .name = "TIMEOUT" },
- [IPSET_ATTR_PROTO] = { .name = "PROTO" },
- [IPSET_ATTR_CADT_FLAGS] = { .name = "CADT_FLAGS" },
- [IPSET_ATTR_CADT_LINENO] = { .name = "CADT_LINENO" },
- [IPSET_ATTR_GC] = { .name = "GC" },
- [IPSET_ATTR_HASHSIZE] = { .name = "HASHSIZE" },
- [IPSET_ATTR_MAXELEM] = { .name = "MAXELEM" },
- [IPSET_ATTR_NETMASK] = { .name = "NETMASK" },
- [IPSET_ATTR_PROBES] = { .name = "PROBES" },
- [IPSET_ATTR_RESIZE] = { .name = "RESIZE" },
- [IPSET_ATTR_SIZE] = { .name = "SIZE" },
- [IPSET_ATTR_ELEMENTS] = { .name = "ELEMENTS" },
- [IPSET_ATTR_REFERENCES] = { .name = "REFERENCES" },
- [IPSET_ATTR_MEMSIZE] = { .name = "MEMSIZE" },
-};
-
-static const struct ipset_attrname adtattr2name[] = {
- [IPSET_ATTR_IP] = { .name = "IP" },
- [IPSET_ATTR_IP_TO] = { .name = "IP_TO" },
- [IPSET_ATTR_CIDR] = { .name = "CIDR" },
- [IPSET_ATTR_PORT] = { .name = "PORT" },
- [IPSET_ATTR_PORT_TO] = { .name = "PORT_TO" },
- [IPSET_ATTR_TIMEOUT] = { .name = "TIMEOUT" },
- [IPSET_ATTR_PROTO] = { .name = "PROTO" },
- [IPSET_ATTR_CADT_FLAGS] = { .name = "CADT_FLAGS" },
- [IPSET_ATTR_CADT_LINENO] = { .name = "CADT_LINENO" },
- [IPSET_ATTR_ETHER] = { .name = "ETHER" },
- [IPSET_ATTR_NAME] = { .name = "NAME" },
- [IPSET_ATTR_NAMEREF] = { .name = "NAMEREF" },
- [IPSET_ATTR_IP2] = { .name = "IP2" },
- [IPSET_ATTR_CIDR2] = { .name = "CIDR2" },
- [IPSET_ATTR_IP2_TO] = { .name = "IP2_TO" },
- [IPSET_ATTR_IFACE] = { .name = "IFACE" },
-};
-
-static void
-debug_cadt_attrs(int max, const struct ipset_attr_policy *policy,
- const struct ipset_attrname attr2name[],
- struct nlattr *nla[])
-{
- uint32_t v;
- int i;
-
- fprintf(stderr, "\t\t%s attributes:\n",
- policy == create_attrs ? "CREATE" : "ADT");
- for (i = IPSET_ATTR_UNSPEC + 1; i <= max; i++) {
- if (!nla[i])
- continue;
- switch (policy[i].type) {
- case MNL_TYPE_U8:
- v = *(uint8_t *) mnl_attr_get_payload(nla[i]);
- fprintf(stderr, "\t\t%s: %u\n",
- attr2name[i].name, v);
- break;
- case MNL_TYPE_U16:
- v = *(uint16_t *) mnl_attr_get_payload(nla[i]);
- fprintf(stderr, "\t\t%s: %u\n",
- attr2name[i].name, ntohs(v));
- break;
- case MNL_TYPE_U32:
- v = *(uint32_t *) mnl_attr_get_payload(nla[i]);
- fprintf(stderr, "\t\t%s: %u\n",
- attr2name[i].name, ntohl(v));
- break;
- case MNL_TYPE_NUL_STRING:
- fprintf(stderr, "\t\t%s: %s\n",
- attr2name[i].name,
- (const char *) mnl_attr_get_payload(nla[i]));
- break;
- case MNL_TYPE_NESTED: {
- struct nlattr *ipattr[IPSET_ATTR_IPADDR_MAX+1] = {};
- char addr[INET6_ADDRSTRLEN];
- void *d;
-
- if (mnl_attr_parse_nested(nla[i], ipaddr_attr_cb,
- ipattr) < 0) {
- fprintf(stderr,
- "\t\tIPADDR: cannot validate "
- "and parse attributes\n");
- continue;
- }
- if (ipattr[IPSET_ATTR_IPADDR_IPV4]) {
- d = mnl_attr_get_payload(
- ipattr[IPSET_ATTR_IPADDR_IPV4]);
-
- inet_ntop(NFPROTO_IPV4, d, addr, INET6_ADDRSTRLEN);
- fprintf(stderr, "\t\t%s: %s\n",
- attr2name[i].name, addr);
- } else if (ipattr[IPSET_ATTR_IPADDR_IPV6]) {
- d = mnl_attr_get_payload(
- ipattr[IPSET_ATTR_IPADDR_IPV6]);
-
- inet_ntop(NFPROTO_IPV6, d, addr, INET6_ADDRSTRLEN);
- fprintf(stderr, "\t\t%s: %s\n",
- attr2name[i].name, addr);
- }
- break;
- }
- default:
- fprintf(stderr, "\t\t%s: unresolved!\n",
- attr2name[i].name);
- }
- }
-}
-
-static void
-debug_cmd_attrs(int cmd, struct nlattr *nla[])
-{
- struct nlattr *adt[IPSET_ATTR_ADT_MAX+1] = {};
- struct nlattr *cattr[IPSET_ATTR_CREATE_MAX+1] = {};
- uint32_t v;
- int i;
-
- fprintf(stderr, "\tCommand attributes:\n");
- for (i = IPSET_ATTR_UNSPEC + 1; i <= IPSET_ATTR_CMD_MAX; i++) {
- if (!nla[i])
- continue;
- switch (cmd_attrs[i].type) {
- case MNL_TYPE_U8:
- v = *(uint8_t *) mnl_attr_get_payload(nla[i]);
- fprintf(stderr, "\t%s: %u\n",
- cmdattr2name[i].name, v);
- break;
- case MNL_TYPE_U16:
- v = *(uint16_t *) mnl_attr_get_payload(nla[i]);
- fprintf(stderr, "\t%s: %u\n",
- cmdattr2name[i].name, ntohs(v));
- break;
- case MNL_TYPE_U32:
- v = *(uint32_t *) mnl_attr_get_payload(nla[i]);
- fprintf(stderr, "\t%s: %u\n",
- cmdattr2name[i].name, ntohl(v));
- break;
- case MNL_TYPE_NUL_STRING:
- fprintf(stderr, "\t%s: %s\n",
- cmdattr2name[i].name,
- (const char *) mnl_attr_get_payload(nla[i]));
- break;
- case MNL_TYPE_NESTED:
- if (i == IPSET_ATTR_DATA) {
- switch (cmd) {
- case IPSET_CMD_ADD:
- case IPSET_CMD_DEL:
- case IPSET_CMD_TEST:
- if (mnl_attr_parse_nested(nla[i],
- adt_attr_cb, adt) < 0) {
- fprintf(stderr,
- "\tADT: cannot validate "
- "and parse attributes\n");
- continue;
- }
- debug_cadt_attrs(IPSET_ATTR_ADT_MAX,
- adt_attrs,
- adtattr2name,
- adt);
- break;
- default:
- if (mnl_attr_parse_nested(nla[i],
- create_attr_cb,
- cattr) < 0) {
- fprintf(stderr,
- "\tCREATE: cannot validate "
- "and parse attributes\n");
- continue;
- }
- debug_cadt_attrs(IPSET_ATTR_CREATE_MAX,
- create_attrs,
- createattr2name,
- cattr);
- }
- } else {
- struct nlattr *tb;
- mnl_attr_for_each_nested(tb, nla[i]) {
- memset(adt, 0, sizeof(adt));
- if (mnl_attr_parse_nested(tb,
- adt_attr_cb, adt) < 0) {
- fprintf(stderr,
- "\tADT: cannot validate "
- "and parse attributes\n");
- continue;
- }
- debug_cadt_attrs(IPSET_ATTR_ADT_MAX,
- adt_attrs,
- adtattr2name,
- adt);
- }
- }
- break;
- default:
- fprintf(stderr, "\t%s: unresolved!\n",
- cmdattr2name[i].name);
- }
- }
-}
-
-void
-ipset_debug_msg(const char *dir, void *buffer, int len)
-{
- const struct nlmsghdr *nlh = buffer;
- struct nlattr *nla[IPSET_ATTR_CMD_MAX+1] = {};
- int cmd, nfmsglen = MNL_ALIGN(sizeof(struct nfgenmsg));
-
- debug = 0;
- while (mnl_nlmsg_ok(nlh, len)) {
- switch (nlh->nlmsg_type) {
- case NLMSG_NOOP:
- case NLMSG_DONE:
- case NLMSG_OVERRUN:
- fprintf(stderr, "Message header: %s msg %s\n"
- "\tlen %d\n"
- "\tseq %u\n",
- dir,
- nlh->nlmsg_type == NLMSG_NOOP ? "NOOP" :
- nlh->nlmsg_type == NLMSG_DONE ? "DONE" :
- "OVERRUN",
- len, nlh->nlmsg_seq);
- goto next_msg;
- case NLMSG_ERROR: {
- const struct nlmsgerr *err = mnl_nlmsg_get_payload(nlh);
- fprintf(stderr, "Message header: %s msg ERROR\n"
- "\tlen %d\n"
- "\terrcode %d\n"
- "\tseq %u\n",
- dir, len, err->error, nlh->nlmsg_seq);
- goto next_msg;
- }
- default:
- ;
- }
- cmd = ipset_get_nlmsg_type(nlh);
- fprintf(stderr, "Message header: %s cmd %s (%d)\n"
- "\tlen %d\n"
- "\tflag %s\n"
- "\tseq %u\n",
- dir,
- cmd <= IPSET_CMD_NONE ? "NONE!" :
- cmd >= IPSET_CMD_MAX ? "MAX!" : cmd2name[cmd], cmd,
- len,
- !(nlh->nlmsg_flags & NLM_F_EXCL) ? "EXIST" : "none",
- nlh->nlmsg_seq);
- if (cmd <= IPSET_CMD_NONE || cmd >= IPSET_CMD_MAX)
- goto next_msg;
- memset(nla, 0, sizeof(nla));
- if (mnl_attr_parse(nlh, nfmsglen,
- cmd_attr_cb, nla) < MNL_CB_STOP) {
- fprintf(stderr, "\tcannot validate "
- "and parse attributes\n");
- goto next_msg;
- }
- debug_cmd_attrs(cmd, nla);
-next_msg:
- nlh = mnl_nlmsg_next(nlh, &len);
- }
- debug = 1;
-}
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <assert.h> /* assert */
-#include <errno.h> /* errno */
-#include <string.h> /* strerror */
-
-#include <libipset/debug.h> /* D() */
-#include <libipset/data.h> /* ipset_data_get */
-#include <libipset/session.h> /* ipset_err */
-#include <libipset/types.h> /* struct ipset_type */
-#include <libipset/utils.h> /* STRNEQ */
-#include <libipset/errcode.h> /* prototypes */
-#include <libipset/linux_ip_set_bitmap.h> /* bitmap specific errcodes */
-#include <libipset/linux_ip_set_hash.h> /* hash specific errcodes */
-#include <libipset/linux_ip_set_list.h> /* list specific errcodes */
-
-/* Core kernel error codes */
-static const struct ipset_errcode_table core_errcode_table[] = {
- /* Generic error codes */
- { 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" },
-
- /* CREATE specific error codes */
- { 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 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,
- "Protocol family not supported by the set type" },
-
- /* DESTROY specific error codes */
- { IPSET_ERR_BUSY, IPSET_CMD_DESTROY,
- "Set cannot be destroyed: it is in use by a kernel component" },
-
- /* FLUSH specific error codes */
-
- /* RENAME specific error codes */
- { IPSET_ERR_EXIST_SETNAME2, IPSET_CMD_RENAME,
- "Set cannot be renamed: a set with the new name already exists" },
- { IPSET_ERR_REFERENCED, IPSET_CMD_RENAME,
- "Set cannot be renamed: it is in use by another system" },
-
- /* SWAP specific error codes */
- { IPSET_ERR_EXIST_SETNAME2, IPSET_CMD_SWAP,
- "Sets cannot be swapped: the second set does not exist" },
- { IPSET_ERR_TYPE_MISMATCH, IPSET_CMD_SWAP,
- "The sets cannot be swapped: they type does not match" },
-
- /* LIST/SAVE specific error codes */
-
- /* Generic (CADT) error codes */
- { IPSET_ERR_INVALID_CIDR, 0,
- "The value of the CIDR parameter of the IP address is invalid" },
- { IPSET_ERR_TIMEOUT, 0,
- "Timeout cannot be used: set was created without timeout support" },
- { IPSET_ERR_IPADDR_IPV4, 0,
- "An IPv4 address is expected, but not received" },
- { IPSET_ERR_IPADDR_IPV6, 0,
- "An IPv6 address is expected, but not received" },
-
- /* ADD specific error codes */
- { IPSET_ERR_EXIST, IPSET_CMD_ADD,
- "Element cannot be added to the set: it's already added" },
-
- /* DEL specific error codes */
- { IPSET_ERR_EXIST, IPSET_CMD_DEL,
- "Element cannot be deleted from the set: it's not added" },
-
- /* TEST specific error codes */
-
- /* HEADER specific error codes */
-
- /* TYPE specific error codes */
- { EEXIST, IPSET_CMD_TYPE,
- "Kernel error received: set type does not supported" },
-
- /* PROTOCOL specific error codes */
-
- { },
-};
-
-/* Bitmap type-specific error codes */
-static const struct ipset_errcode_table bitmap_errcode_table[] = {
- /* Generic (CADT) error codes */
- { IPSET_ERR_BITMAP_RANGE, 0,
- "Element is out of the range of the set" },
- { IPSET_ERR_BITMAP_RANGE_SIZE, IPSET_CMD_CREATE,
- "The range you specified exceeds the size limit of the set type" },
- { },
-};
-
-/* Hash type-specific error codes */
-static const struct ipset_errcode_table hash_errcode_table[] = {
- /* Generic (CADT) error codes */
- { IPSET_ERR_HASH_FULL, 0,
- "Hash is full, cannot add more elements" },
- { IPSET_ERR_HASH_ELEM, 0,
- "Null-valued element, cannot be stored in a hash type of set" },
- { IPSET_ERR_INVALID_PROTO, 0,
- "Invalid protocol specified" },
- { IPSET_ERR_MISSING_PROTO, 0,
- "Protocol missing, but must be specified" },
- { IPSET_ERR_HASH_RANGE_UNSUPPORTED, 0,
- "Range is not supported in the \"net\" component of the element" },
- { IPSET_ERR_HASH_RANGE, 0,
- "Invalid range, covers the whole address space" },
- { },
-};
-
-/* List type-specific error codes */
-static const struct ipset_errcode_table list_errcode_table[] = {
- /* Generic (CADT) error codes */
- { IPSET_ERR_NAME, 0,
- "Set to be added/deleted/tested as element does not exist." },
- { IPSET_ERR_LOOP, 0,
- "Sets with list:set type cannot be added to the set." },
- { IPSET_ERR_BEFORE, 0,
- "No reference set specified." },
- { IPSET_ERR_NAMEREF, 0,
- "The set to which you referred with 'before' or 'after' "
- "does not exist." },
- { IPSET_ERR_LIST_FULL, 0,
- "The set is full, more elements cannot be added." },
- { IPSET_ERR_REF_EXIST, 0,
- "The set to which you referred with 'before' or 'after' "
- "is not added to the set." },
- { },
-};
-
-#define MATCH_TYPENAME(a, b) STRNEQ(a, b, strlen(b))
-
-/**
- * ipset_errcode - interpret a kernel error code
- * @session: session structure
- * @errcode: errcode
- *
- * Find the error code and print the appropriate
- * error message into the error buffer.
- *
- * Returns -1.
- */
-int
-ipset_errcode(struct ipset_session *session, enum ipset_cmd cmd, int errcode)
-{
- const struct ipset_errcode_table *table = core_errcode_table;
- int i, generic;
-
- if (errcode >= IPSET_ERR_TYPE_SPECIFIC) {
- const struct ipset_type *type;
-
- type = ipset_saved_type(session);
- if (type) {
- if (MATCH_TYPENAME(type->name, "bitmap:"))
- table = bitmap_errcode_table;
- else if (MATCH_TYPENAME(type->name, "hash:"))
- table = hash_errcode_table;
- else if (MATCH_TYPENAME(type->name, "list:"))
- table = list_errcode_table;
- }
- }
-
-retry:
- for (i = 0, generic = -1; table[i].errcode; i++) {
- if (table[i].errcode == errcode &&
- (table[i].cmd == cmd || table[i].cmd == 0)) {
- if (table[i].cmd == 0) {
- generic = i;
- continue;
- }
- return ipset_err(session, table[i].message);
- }
- }
- if (generic != -1)
- return ipset_err(session, table[generic].message);
- /* Fall back to the core table */
- if (table != core_errcode_table) {
- table = core_errcode_table;
- goto retry;
- }
- if (errcode < IPSET_ERR_PRIVATE)
- return ipset_err(session, "Kernel error received: %s",
- strerror(errcode));
- else
- return ipset_err(session,
- "Undecoded error %u received from kernel",
- errcode);
-}
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <libipset/utils.h> /* STRNEQ */
-#include <libipset/icmp.h> /* prototypes */
-
-struct icmp_names {
- const char *name;
- uint8_t type, code;
-};
-
-static const struct icmp_names icmp_typecodes[] = {
- { "echo-reply", 0, 0 },
- { "pong", 0, 0 },
- { "network-unreachable", 3, 0 },
- { "host-unreachable", 3, 1 },
- { "protocol-unreachable", 3, 2 },
- { "port-unreachable", 3, 3 },
- { "fragmentation-needed", 3, 4 },
- { "source-route-failed", 3, 5 },
- { "network-unknown", 3, 6 },
- { "host-unknown", 3, 7 },
- { "network-prohibited", 3, 9 },
- { "host-prohibited", 3, 10 },
- { "TOS-network-unreachable", 3, 11 },
- { "TOS-host-unreachable", 3, 12 },
- { "communication-prohibited", 3, 13 },
- { "host-precedence-violation", 3, 14 },
- { "precedence-cutoff", 3, 15 },
- { "source-quench", 4, 0 },
- { "network-redirect", 5, 0 },
- { "host-redirect", 5, 1 },
- { "TOS-network-redirect", 5, 2 },
- { "TOS-host-redirect", 5, 3 },
- { "echo-request", 8, 0 },
- { "ping", 8, 0 },
- { "router-advertisement", 9, 0 },
- { "router-solicitation", 10, 0 },
- { "ttl-zero-during-transit", 11, 0 },
- { "ttl-zero-during-reassembly", 11, 1 },
- { "ip-header-bad", 12, 0 },
- { "required-option-missing", 12, 1 },
- { "timestamp-request", 13, 0 },
- { "timestamp-reply", 14, 0 },
- { "address-mask-request", 17, 0 },
- { "address-mask-reply", 18, 0 },
-};
-
-const char *id_to_icmp(uint8_t id)
-{
- return id < ARRAY_SIZE(icmp_typecodes) ? icmp_typecodes[id].name : NULL;
-}
-
-const char *icmp_to_name(uint8_t type, uint8_t code)
-{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(icmp_typecodes); i++)
- if (icmp_typecodes[i].type == type &&
- icmp_typecodes[i].code == code)
- return icmp_typecodes[i].name;
-
- return NULL;
-}
-
-int name_to_icmp(const char *str, uint16_t *typecode)
-{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(icmp_typecodes); i++)
- if (STRNCASEQ(icmp_typecodes[i].name, str, strlen(str))) {
- *typecode = (icmp_typecodes[i].type << 8) |
- icmp_typecodes[i].code;
- return 0;
- }
-
- return -1;
-}
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <libipset/utils.h> /* STRNEQ */
-#include <libipset/icmpv6.h> /* prototypes */
-
-struct icmpv6_names {
- const char *name;
- uint8_t type, code;
-};
-
-static const struct icmpv6_names icmpv6_typecodes[] = {
- { "no-route", 1, 0 },
- { "communication-prohibited", 1, 1 },
- { "address-unreachable", 1, 3 },
- { "port-unreachable", 1, 4 },
- { "packet-too-big", 2, 0 },
- { "ttl-zero-during-transit", 3, 0 },
- { "ttl-zero-during-reassembly", 3, 1 },
- { "bad-header", 4, 0 },
- { "unknown-header-type", 4, 1 },
- { "unknown-option", 4, 2 },
- { "echo-request", 128, 0 },
- { "ping", 128, 0 },
- { "echo-reply", 129, 0 },
- { "pong", 129, 0 },
- { "router-solicitation", 133, 0 },
- { "router-advertisement", 134, 0 },
- { "neighbour-solicitation", 135, 0 },
- { "neigbour-solicitation", 135, 0 },
- { "neighbour-advertisement", 136, 0 },
- { "neigbour-advertisement", 136, 0 },
- { "redirect", 137, 0 },
-};
-
-const char *id_to_icmpv6(uint8_t id)
-{
- return id < ARRAY_SIZE(icmpv6_typecodes) ?
- icmpv6_typecodes[id].name : NULL;
-}
-
-const char *icmpv6_to_name(uint8_t type, uint8_t code)
-{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(icmpv6_typecodes); i++)
- if (icmpv6_typecodes[i].type == type &&
- icmpv6_typecodes[i].code == code)
- return icmpv6_typecodes[i].name;
-
- return NULL;
-}
-
-int name_to_icmpv6(const char *str, uint16_t *typecode)
-{
- unsigned int i;
-
- for (i = 0; i < ARRAY_SIZE(icmpv6_typecodes); i++)
- if (STRNCASEQ(icmpv6_typecodes[i].name, str, strlen(str))) {
- *typecode = (icmpv6_typecodes[i].type << 8) |
- icmpv6_typecodes[i].code;
- return 0;
- }
-
- return -1;
-}
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <assert.h> /* assert */
-#include <errno.h> /* errno */
-#include <stdint.h>
-#include <stdlib.h> /* calloc, free */
-#include <time.h> /* time */
-#include <arpa/inet.h> /* hto* */
-
-#include <libipset/linux_ip_set.h> /* enum ipset_cmd */
-#include <libipset/debug.h> /* D() */
-#include <libipset/session.h> /* ipset_session_handle */
-#include <libipset/ui.h> /* IPSET_ENV_EXIST */
-#include <libipset/utils.h> /* UNUSED */
-#include <libipset/mnl.h> /* prototypes */
-
-#include <libmnl/libmnl.h>
-#include <linux/genetlink.h>
-#include <linux/netlink.h>
-
-#ifndef NFNL_SUBSYS_IPSET
-#define NFNL_SUBSYS_IPSET 6
-#endif
-
-/* Internal data structure for the kernel-userspace communication parameters */
-struct ipset_handle {
- struct mnl_socket *h; /* the mnl socket */
- unsigned int seq; /* netlink message sequence number */
- unsigned int portid; /* the socket port identifier */
- mnl_cb_t *cb_ctl; /* control block callbacks */
- void *data; /* data pointer */
- unsigned int genl_id; /* genetlink ID of ip_set */
-};
-
-/* Netlink flags of the commands */
-static const uint16_t cmdflags[] = {
- [IPSET_CMD_CREATE-1] = NLM_F_REQUEST|NLM_F_ACK|
- NLM_F_CREATE|NLM_F_EXCL,
- [IPSET_CMD_DESTROY-1] = NLM_F_REQUEST|NLM_F_ACK,
- [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|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,
- [IPSET_CMD_HEADER-1] = NLM_F_REQUEST,
- [IPSET_CMD_TYPE-1] = NLM_F_REQUEST,
- [IPSET_CMD_PROTOCOL-1] = NLM_F_REQUEST,
-};
-
-/**
- * ipset_get_nlmsg_type - get ipset netlink message type
- * @nlh: pointer to the netlink message header
- *
- * Returns the ipset netlink message type, i.e. the ipset command.
- */
-int
-ipset_get_nlmsg_type(const struct nlmsghdr *nlh)
-{
- const struct genlmsghdr *ghdr = mnl_nlmsg_get_payload(nlh);
-
- return ghdr->cmd;
-}
-
-static void
-ipset_mnl_fill_hdr(struct ipset_handle *handle, enum ipset_cmd cmd,
- void *buffer, size_t len UNUSED, uint8_t envflags)
-{
- struct nlmsghdr *nlh;
- struct genlmsghdr *ghdr;
-
- assert(handle);
- assert(buffer);
- assert(cmd > IPSET_CMD_NONE && cmd < IPSET_MSG_MAX);
-
- nlh = mnl_nlmsg_put_header(buffer);
- nlh->nlmsg_type = handle->genl_id;
- nlh->nlmsg_flags = NLM_F_REQUEST;
- if (cmdflags[cmd-1] & NLM_F_ACK)
- nlh->nlmsg_flags |= NLM_F_ACK;
-
- ghdr = mnl_nlmsg_put_extra_header(nlh, sizeof(struct genlmsghdr));
- ghdr->cmd = cmd;
- /* (ge)netlink is dumb, NLM_F_CREATE and NLM_F_DUMP overlap, get misinterpreted. */
- ghdr->reserved = cmdflags[cmd-1];
- if (envflags & IPSET_ENV_EXIST)
- ghdr->reserved &= ~NLM_F_EXCL;
-}
-
-static int
-ipset_mnl_query(struct ipset_handle *handle, void *buffer, size_t len)
-{
- struct nlmsghdr *nlh = buffer;
- int ret;
-
- assert(handle);
- assert(buffer);
-
- nlh->nlmsg_seq = ++handle->seq;
-#ifdef IPSET_DEBUG
- ipset_debug_msg("sent", nlh, nlh->nlmsg_len);
-#endif
- if (mnl_socket_sendto(handle->h, nlh, nlh->nlmsg_len) < 0)
- return -ECOMM;
-
- ret = mnl_socket_recvfrom(handle->h, buffer, len);
-#ifdef IPSET_DEBUG
- ipset_debug_msg("received", buffer, ret);
-#endif
- while (ret > 0) {
- ret = mnl_cb_run2(buffer, ret,
- handle->seq, handle->portid,
- handle->cb_ctl[NLMSG_MIN_TYPE],
- handle->data,
- handle->cb_ctl, NLMSG_MIN_TYPE);
- D("nfln_cb_run2, ret: %d, errno %d", ret, errno);
- if (ret <= 0)
- break;
- ret = mnl_socket_recvfrom(handle->h, buffer, len);
- D("message received, ret: %d", ret);
- }
- return ret > 0 ? 0 : ret;
-}
-
-static int ipset_mnl_getid_acb(const struct nlattr *attr, void *datap)
-{
- const struct nlattr **tb = datap;
- uint16_t type = mnl_attr_get_type(attr);
-
- if (mnl_attr_type_valid(attr, CTRL_ATTR_MAX) < 0)
- return MNL_CB_OK;
- tb[type] = attr;
- return MNL_CB_OK;
-}
-
-static int ipset_mnl_getid_cb(const struct nlmsghdr *nlhdr, void *datap)
-{
- struct ipset_handle *h = datap;
- const struct nlattr *tb[CTRL_ATTR_MAX+1] = {0};
- const struct genlmsghdr *ghdr = mnl_nlmsg_get_payload(nlhdr);
- int ret;
-
- ret = mnl_attr_parse(nlhdr, sizeof(*ghdr), ipset_mnl_getid_acb, tb);
- if (ret != MNL_CB_OK)
- return ret;
- if (tb[CTRL_ATTR_FAMILY_ID] != NULL)
- h->genl_id = mnl_attr_get_u16(tb[CTRL_ATTR_FAMILY_ID]);
- return MNL_CB_OK;
-}
-
-/**
- * Look up the GENL identifier for the ip_set subsystem, and store it in
- * @h->genl_id. On success, 0 is returned, otherwise error encoded as
- * negative number.
- */
-static int ipset_mnl_getid(struct ipset_handle *h, bool modprobe)
-{
- size_t buf_size = 8192; //MNL_SOCKET_BUFFER_SIZE;
- struct nlmsghdr *nlhdr;
- struct genlmsghdr *ghdr;
- char *buf;
- int ret = -ENOENT;
-
- h->genl_id = 0;
-
- if (modprobe) {
- /* genetlink has no autoloading like nfnetlink... */
- system("/sbin/modprobe -q ip_set");
- }
-
- buf = malloc(buf_size);
- if (buf == NULL)
- return -errno;
-
- nlhdr = mnl_nlmsg_put_header(buf);
- nlhdr->nlmsg_type = GENL_ID_CTRL;
- nlhdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
- ghdr = mnl_nlmsg_put_extra_header(nlhdr, sizeof(struct genlmsghdr));
- ghdr->cmd = CTRL_CMD_GETFAMILY;
- ghdr->version = 2;
- if (!mnl_attr_put_strz_check(nlhdr, buf_size,
- CTRL_ATTR_FAMILY_NAME, "ip_set"))
- goto out;
-
- ret = mnl_socket_sendto(h->h, buf, nlhdr->nlmsg_len);
- if (ret < 0)
- goto out;
- ret = mnl_socket_recvfrom(h->h, buf, buf_size);
- while (ret > 0) {
- ret = mnl_cb_run(buf, ret, 0, 0, ipset_mnl_getid_cb, h);
- if (ret <= 0)
- break;
- ret = mnl_socket_recvfrom(h->h, buf, buf_size);
- }
- if (h->genl_id == 0 && !modprobe)
- /* Redo, with modprobe this time. */
- ret = ipset_mnl_getid(h, true);
- if (h->genl_id > 0)
- ret = 0;
- out:
- free(buf);
- return ret;
-}
-
-static struct ipset_handle *
-ipset_mnl_init(mnl_cb_t *cb_ctl, void *data)
-{
- struct ipset_handle *handle;
-
- assert(cb_ctl);
- assert(data);
-
- handle = calloc(1, sizeof(*handle));
- if (!handle)
- return NULL;
-
- handle->h = mnl_socket_open(NETLINK_GENERIC);
- if (!handle->h)
- goto free_handle;
-
- if (mnl_socket_bind(handle->h, 0, MNL_SOCKET_AUTOPID) < 0)
- goto close_nl;
-
- 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;
- return handle;
-
-close_nl:
- mnl_socket_close(handle->h);
-free_handle:
- free(handle);
-
- return NULL;
-}
-
-static int
-ipset_mnl_fini(struct ipset_handle *handle)
-{
- assert(handle);
-
- if (handle->h)
- mnl_socket_close(handle->h);
-
- free(handle);
- return 0;
-}
-
-const struct ipset_transport ipset_mnl_transport = {
- .init = ipset_mnl_init,
- .fini = ipset_mnl_fini,
- .fill_hdr = ipset_mnl_fill_hdr,
- .query = ipset_mnl_query,
-};
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <assert.h> /* assert */
-#include <errno.h> /* errno */
-#include <limits.h> /* ULLONG_MAX */
-#include <netdb.h> /* getservbyname, getaddrinfo */
-#include <stdlib.h> /* strtoull, etc. */
-#include <sys/types.h> /* getaddrinfo */
-#include <sys/socket.h> /* getaddrinfo, AF_ */
-#include <net/ethernet.h> /* ETH_ALEN */
-#include <net/if.h> /* IFNAMSIZ */
-#include <netinet/in.h> /* IPPROTO_ */
-
-#include <libipset/debug.h> /* D() */
-#include <libipset/data.h> /* IPSET_OPT_* */
-#include <libipset/icmp.h> /* name_to_icmp */
-#include <libipset/icmpv6.h> /* name_to_icmpv6 */
-#include <libipset/pfxlen.h> /* prefixlen_netmask_map */
-#include <libipset/session.h> /* ipset_err */
-#include <libipset/types.h> /* ipset_type_get */
-#include <libipset/utils.h> /* string utilities */
-#include <libipset/parse.h> /* prototypes */
-
-#ifndef ULLONG_MAX
-#define ULLONG_MAX 18446744073709551615ULL
-#endif
-
-/* Parse input data */
-
-#define cidr_separator(str) ipset_strchr(str, IPSET_CIDR_SEPARATOR)
-#define range_separator(str) ipset_strchr(str, IPSET_RANGE_SEPARATOR)
-#define elem_separator(str) ipset_strchr(str, IPSET_ELEM_SEPARATOR)
-#define name_separator(str) ipset_strchr(str, IPSET_NAME_SEPARATOR)
-#define proto_separator(str) ipset_strchr(str, IPSET_PROTO_SEPARATOR)
-
-#define syntax_err(fmt, args...) \
- ipset_err(session, "Syntax error: " fmt , ## args)
-
-static char *
-ipset_strchr(const char *str, const char *sep)
-{
- char *match;
-
- assert(str);
- assert(sep);
-
- for (; *sep != '\0'; sep++) {
- match = strchr(str, sep[0]);
- if (match != NULL &&
- str[0] != sep[0] &&
- str[strlen(str)-1] != sep[0])
- return match;
- }
-
- return NULL;
-}
-
-/*
- * Parser functions, shamelessly taken from iptables.c, ip6tables.c
- * and parser.c from libnetfilter_conntrack.
- */
-
-/*
- * Parse numbers
- */
-static int
-string_to_number_ll(struct ipset_session *session,
- const char *str,
- unsigned long long min,
- unsigned long long max,
- unsigned long long *ret)
-{
- unsigned long long number = 0;
- char *end;
-
- /* Handle hex, octal, etc. */
- errno = 0;
- number = strtoull(str, &end, 0);
- if (*end == '\0' && end != str && errno != ERANGE) {
- /* we parsed a number, let's see if we want this */
- if (min <= number && (!max || number <= max)) {
- *ret = number;
- return 0;
- } else
- errno = ERANGE;
- }
- if (errno == ERANGE && max)
- return syntax_err("'%s' is out of range %llu-%llu",
- str, min, max);
- else if (errno == ERANGE)
- return syntax_err("'%s' is out of range %llu-%llu",
- str, min, ULLONG_MAX);
- else
- return syntax_err("'%s' is invalid as number", str);
-}
-
-static int
-string_to_u8(struct ipset_session *session,
- const char *str, uint8_t *ret)
-{
- int err;
- unsigned long long num = 0;
-
- err = string_to_number_ll(session, str, 0, 255, &num);
- *ret = num;
-
- return err;
-}
-
-static int
-string_to_cidr(struct ipset_session *session,
- const char *str, uint8_t min, uint8_t max, uint8_t *ret)
-{
- int err = string_to_u8(session, str, ret);
-
- if (!err && (*ret < min || *ret > max))
- return syntax_err("'%s' is out of range %u-%u",
- str, min, max);
-
- return err;
-}
-
-static int
-string_to_u16(struct ipset_session *session,
- const char *str, uint16_t *ret)
-{
- int err;
- unsigned long long num = 0;
-
- err = string_to_number_ll(session, str, 0, USHRT_MAX, &num);
- *ret = num;
-
- return err;
-}
-
-static int
-string_to_u32(struct ipset_session *session,
- const char *str, uint32_t *ret)
-{
- int err;
- unsigned long long num = 0;
-
- err = string_to_number_ll(session, str, 0, UINT_MAX, &num);
- *ret = num;
-
- return err;
-}
-
-/**
- * ipset_parse_ether - parse ethernet address
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- *
- * Parse string as an ethernet address. The parsed ethernet
- * address is stored in the data blob of the session.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_ether(struct ipset_session *session,
- enum ipset_opt opt, const char *str)
-{
- unsigned int i = 0;
- unsigned char ether[ETH_ALEN];
-
- assert(session);
- assert(opt == IPSET_OPT_ETHER);
- assert(str);
-
- if (strlen(str) != ETH_ALEN * 3 - 1)
- goto error;
-
- for (i = 0; i < ETH_ALEN; i++) {
- long number;
- char *end;
-
- number = strtol(str + i * 3, &end, 16);
-
- if (end == str + i * 3 + 2 &&
- (*end == ':' || *end == '\0') &&
- number >= 0 && number <= 255)
- ether[i] = number;
- else
- goto error;
- }
- return ipset_session_data_set(session, opt, ether);
-
-error:
- return syntax_err("cannot parse '%s' as ethernet address", str);
-}
-
-/*
- * Parse TCP service names or port numbers
- */
-static int
-parse_portname(struct ipset_session *session, const char *str,
- uint16_t *port, const char *proto)
-{
- struct servent *service = getservbyname(str, proto);
-
- if (service != NULL) {
- *port = ntohs((uint16_t) service->s_port);
- return 0;
- }
-
- return syntax_err("cannot parse '%s' as a %s port", str, proto);
-}
-
-/**
- * ipset_parse_single_port - parse a single port number or name
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- * @proto: protocol
- *
- * Parse string as a single port number or name. The parsed port
- * number is stored in the data blob of the session.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_port(struct ipset_session *session,
- enum ipset_opt opt, const char *str,
- const char *proto)
-{
- uint16_t port;
- int err;
-
- assert(session);
- assert(opt == IPSET_OPT_PORT || opt == IPSET_OPT_PORT_TO);
- assert(str);
-
- if ((err = string_to_u16(session, str, &port)) == 0 ||
- (err = parse_portname(session, str, &port, proto)) == 0)
- err = ipset_session_data_set(session, opt, &port);
-
- if (!err)
- /* No error, so reset false error messages! */
- ipset_session_report_reset(session);
-
- return err;
-}
-
-/**
- * ipset_parse_tcpudp_port - parse TCP/UDP port name, number, or range of them
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- * @proto: TCP|UDP
- *
- * Parse string as a TCP/UDP port name or number or range of them
- * separated by a dash. The parsed port numbers are stored
- * in the data blob of the session.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_tcpudp_port(struct ipset_session *session,
- enum ipset_opt opt, const char *str, const char *proto)
-{
- char *a, *saved, *tmp;
- int err = 0;
-
- assert(session);
- assert(opt == IPSET_OPT_PORT);
- assert(str);
-
- saved = tmp = strdup(str);
- if (tmp == NULL)
- return ipset_err(session,
- "Cannot allocate memory to duplicate %s.",
- str);
-
- a = range_separator(tmp);
- if (a != NULL) {
- /* port-port */
- *a++ = '\0';
- err = ipset_parse_port(session, IPSET_OPT_PORT_TO, a, proto);
- if (err)
- goto error;
- }
- err = ipset_parse_port(session, opt, tmp, proto);
-
-error:
- free(saved);
- return err;
-}
-
-/**
- * ipset_parse_tcp_port - parse TCP port name, number, or range of them
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- *
- * Parse string as a TCP port name or number or range of them
- * separated by a dash. The parsed port numbers are stored
- * in the data blob of the session.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_tcp_port(struct ipset_session *session,
- enum ipset_opt opt, const char *str)
-{
- return ipset_parse_tcpudp_port(session, opt, str, "tcp");
-}
-
-/**
- * ipset_parse_single_tcp_port - parse TCP port name or number
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- *
- * Parse string as a single TCP port name or number.
- * The parsed port number is stored
- * in the data blob of the session.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_single_tcp_port(struct ipset_session *session,
- enum ipset_opt opt, const char *str)
-{
- assert(session);
- assert(opt == IPSET_OPT_PORT || opt == IPSET_OPT_PORT_TO);
- assert(str);
-
- return ipset_parse_port(session, opt, str, "tcp");
-}
-
-/**
- * ipset_parse_proto - parse protocol name
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- *
- * Parse string as a protocol name.
- * The parsed protocol is stored in the data blob of the session.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_proto(struct ipset_session *session,
- enum ipset_opt opt, const char *str)
-{
- const struct protoent *protoent;
- uint8_t proto = 0;
-
- assert(session);
- assert(opt == IPSET_OPT_PROTO);
- assert(str);
-
- protoent = getprotobyname(strcasecmp(str, "icmpv6") == 0
- ? "ipv6-icmp" : str);
- if (protoent == NULL)
- return syntax_err("cannot parse '%s' "
- "as a protocol name", str);
- proto = protoent->p_proto;
- if (!proto)
- return syntax_err("Unsupported protocol '%s'", str);
-
- return ipset_session_data_set(session, opt, &proto);
-}
-
-/* Parse ICMP and ICMPv6 type/code */
-static int
-parse_icmp_typecode(struct ipset_session *session,
- enum ipset_opt opt, const char *str,
- const char *family)
-{
- uint16_t typecode;
- uint8_t type, code;
- char *a, *saved, *tmp;
- int err;
-
- saved = tmp = strdup(str);
- if (tmp == NULL)
- return ipset_err(session,
- "Cannot allocate memory to duplicate %s.",
- str);
- a = cidr_separator(tmp);
- if (a == NULL) {
- free(saved);
- return ipset_err(session,
- "Cannot parse %s as an %s type/code.",
- str, family);
- }
- *a++ = '\0';
- if ((err = string_to_u8(session, tmp, &type)) != 0 ||
- (err = string_to_u8(session, a, &code)) != 0)
- goto error;
-
- typecode = (type << 8) | code;
- err = ipset_session_data_set(session, opt, &typecode);
-
-error:
- free(saved);
- return err;
-}
-
-/**
- * ipset_parse_icmp - parse an ICMP name or type/code
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- *
- * Parse string as an ICMP name or type/code numbers.
- * The parsed ICMP type/code is stored in the data blob of the session.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_icmp(struct ipset_session *session,
- enum ipset_opt opt, const char *str)
-{
- uint16_t typecode;
-
- assert(session);
- assert(opt == IPSET_OPT_PORT);
- assert(str);
-
- if (name_to_icmp(str, &typecode) < 0)
- return parse_icmp_typecode(session, opt, str, "ICMP");
-
- return ipset_session_data_set(session, opt, &typecode);
-}
-
-/**
- * ipset_parse_icmpv6 - parse an ICMPv6 name or type/code
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- *
- * Parse string as an ICMPv6 name or type/code numbers.
- * The parsed ICMPv6 type/code is stored in the data blob of the session.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_icmpv6(struct ipset_session *session,
- enum ipset_opt opt, const char *str)
-{
- uint16_t typecode;
-
- assert(session);
- assert(opt == IPSET_OPT_PORT);
- assert(str);
-
- if (name_to_icmpv6(str, &typecode) < 0)
- return parse_icmp_typecode(session, opt, str, "ICMPv6");
-
- return ipset_session_data_set(session, opt, &typecode);
-}
-
-/**
- * ipset_parse_proto_port - parse (optional) protocol and a single port
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- *
- * Parse string as a protocol and port, separated by a colon.
- * The protocol part is optional.
- * The parsed protocol and port numbers are stored in the data
- * blob of the session.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_proto_port(struct ipset_session *session,
- enum ipset_opt opt, const char *str)
-{
- struct ipset_data *data;
- char *a, *saved, *tmp;
- const char *proto;
- uint8_t p = IPPROTO_TCP;
- int err = 0;
-
- assert(session);
- assert(opt == IPSET_OPT_PORT);
- assert(str);
-
- data = ipset_session_data(session);
- saved = tmp = strdup(str);
- if (tmp == NULL)
- return ipset_err(session,
- "Cannot allocate memory to duplicate %s.",
- str);
-
- a = proto_separator(tmp);
- if (a != NULL) {
- uint8_t family = ipset_data_family(data);
-
- /* proto:port */
- *a++ = '\0';
- err = ipset_parse_proto(session, IPSET_OPT_PROTO, tmp);
- if (err)
- goto error;
-
- p = *(const uint8_t *) ipset_data_get(data, IPSET_OPT_PROTO);
- switch (p) {
- case IPPROTO_TCP:
- case IPPROTO_SCTP:
- case IPPROTO_UDP:
- case IPPROTO_UDPLITE:
- proto = tmp;
- tmp = a;
- goto parse_port;
- case IPPROTO_ICMP:
- if (family != NFPROTO_IPV4) {
- syntax_err("Protocol ICMP can be used "
- "with family INET only");
- goto error;
- }
- err = ipset_parse_icmp(session, opt, a);
- break;
- case IPPROTO_ICMPV6:
- if (family != NFPROTO_IPV6) {
- syntax_err("Protocol ICMPv6 can be used "
- "with family INET6 only");
- goto error;
- }
- err = ipset_parse_icmpv6(session, opt, a);
- break;
- default:
- if (!STREQ(a, "0")) {
- syntax_err("Protocol %s can be used "
- "with pseudo port value 0 only.");
- goto error;
- }
- ipset_data_flags_set(data, IPSET_FLAG(opt));
- }
- goto error;
- } else {
- proto = "TCP";
- err = ipset_data_set(data, IPSET_OPT_PROTO, &p);
- if (err)
- goto error;
- }
-parse_port:
- err = ipset_parse_tcpudp_port(session, opt, tmp, proto);
-
-error:
- free(saved);
- return err;
-}
-
-/**
- * ipset_parse_family - parse INET|INET6 family names
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- *
- * Parse string as an INET|INET6 family name.
- * The value is stored in the data blob of the session.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_family(struct ipset_session *session,
- enum ipset_opt opt, const char *str)
-{
- struct ipset_data *data;
- uint8_t family;
-
- assert(session);
- assert(opt == IPSET_OPT_FAMILY);
- assert(str);
-
- data = ipset_session_data(session);
- if (ipset_data_flags_test(data, IPSET_FLAG(IPSET_OPT_FAMILY)))
- syntax_err("protocol family may not be specified "
- "multiple times");
-
- if (STREQ(str, "inet") || STREQ(str, "ipv4") || STREQ(str, "-4"))
- family = NFPROTO_IPV4;
- else if (STREQ(str, "inet6") || STREQ(str, "ipv6") || STREQ(str, "-6"))
- family = NFPROTO_IPV6;
- else if (STREQ(str, "any") || STREQ(str, "unspec"))
- family = NFPROTO_UNSPEC;
- else
- return syntax_err("unknown INET family %s", str);
-
- return ipset_data_set(data, opt, &family);
-}
-
-/*
- * Parse IPv4/IPv6 addresses, networks and ranges.
- * We resolve hostnames but just the first IP address is used.
- */
-
-static struct addrinfo *
-call_getaddrinfo(struct ipset_session *session, const char *str,
- uint8_t family)
-{
- struct addrinfo hints;
- struct addrinfo *res;
- int err;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_flags = AI_CANONNAME;
- hints.ai_family = family;
- hints.ai_socktype = SOCK_RAW;
- hints.ai_protocol = 0;
- hints.ai_next = NULL;
-
- if ((err = getaddrinfo(str, NULL, &hints, &res)) != 0) {
- syntax_err("cannot resolve '%s' to an %s address: %s",
- str, family == NFPROTO_IPV6 ? "IPv6" : "IPv4",
- gai_strerror(err));
- return NULL;
- } else
- return res;
-}
-
-static int
-get_addrinfo(struct ipset_session *session,
- enum ipset_opt opt,
- const char *str,
- struct addrinfo **info,
- uint8_t family)
-{
- struct addrinfo *i;
- size_t addrlen = family == NFPROTO_IPV4 ? sizeof(struct sockaddr_in)
- : sizeof(struct sockaddr_in6);
- int found, err = 0;
-
- if ((*info = call_getaddrinfo(session, str, family)) == NULL) {
- syntax_err("cannot parse %s: resolving to %s address failed",
- str, family == NFPROTO_IPV4 ? "IPv4" : "IPv6");
- return EINVAL;
- }
-
- for (i = *info, found = 0; i != NULL; i = i->ai_next) {
- if (i->ai_family != family || i->ai_addrlen != addrlen)
- continue;
- if (found == 0) {
- if (family == NFPROTO_IPV4) {
- /* Workaround: direct cast increases
- * required alignment on Sparc
- */
- const struct sockaddr_in *saddr =
- (void *)i->ai_addr;
- err = ipset_session_data_set(session,
- opt, &saddr->sin_addr);
- } else {
- /* Workaround: direct cast increases
- * required alignment on Sparc
- */
- const struct sockaddr_in6 *saddr =
- (void *)i->ai_addr;
- err = ipset_session_data_set(session,
- opt, &saddr->sin6_addr);
- }
- } else if (found == 1) {
- ipset_warn(session,
- "%s resolves to multiple addresses: "
- "using only the first one returned "
- "by the resolver",
- str);
- }
- found++;
- }
- if (found == 0)
- return syntax_err("cannot parse %s: "
- "%s address could not be resolved",
- str, family == NFPROTO_IPV4 ? "IPv4" : "IPv6");
- return err;
-}
-
-static int
-parse_ipaddr(struct ipset_session *session,
- enum ipset_opt opt, const char *str,
- uint8_t family)
-{
- uint8_t m = family == NFPROTO_IPV4 ? 32 : 128;
- int aerr = EINVAL, err = 0, range = 0;
- char *saved = strdup(str);
- char *a, *tmp = saved;
- struct addrinfo *info;
- enum ipset_opt copt, opt2;
-
- if (opt == IPSET_OPT_IP) {
- copt = IPSET_OPT_CIDR;
- opt2 = IPSET_OPT_IP_TO;
- } else {
- copt = IPSET_OPT_CIDR2;
- opt2 = IPSET_OPT_IP2_TO;
- }
-
- if (tmp == NULL)
- return ipset_err(session,
- "Cannot allocate memory to duplicate %s.",
- str);
- if ((a = cidr_separator(tmp)) != NULL) {
- /* IP/mask */
- *a++ = '\0';
-
- if ((err = string_to_cidr(session, a, 0, m, &m)) != 0 ||
- (err = ipset_session_data_set(session, copt, &m)) != 0)
- goto out;
- } else if ((a = range_separator(tmp)) != NULL) {
- /* IP-IP */
- *a++ = '\0';
- D("range %s", a);
- range++;
- }
- if ((aerr = get_addrinfo(session, opt, tmp, &info, family)) != 0 ||
- !range)
- goto out;
- freeaddrinfo(info);
- aerr = get_addrinfo(session, opt2, a, &info, family);
-
-out:
- if (aerr != EINVAL)
- /* getaddrinfo not failed */
- freeaddrinfo(info);
- else if (aerr)
- err = -1;
- free(saved);
- return err;
-}
-
-enum ipaddr_type {
- IPADDR_ANY,
- IPADDR_PLAIN,
- IPADDR_NET,
- IPADDR_RANGE,
-};
-
-static inline bool
-cidr_hostaddr(const char *str, uint8_t family)
-{
- char *a = cidr_separator(str);
-
- return family == NFPROTO_IPV4 ? STREQ(a, "/32") : STREQ(a, "/128");
-}
-
-static int
-parse_ip(struct ipset_session *session,
- enum ipset_opt opt, const char *str, enum ipaddr_type addrtype)
-{
- struct ipset_data *data = ipset_session_data(session);
- uint8_t family = ipset_data_family(data);
-
- if (family == NFPROTO_UNSPEC) {
- family = NFPROTO_IPV4;
- ipset_data_set(data, IPSET_OPT_FAMILY, &family);
- }
-
- switch (addrtype) {
- case IPADDR_PLAIN:
- if (range_separator(str) ||
- (cidr_separator(str) && !cidr_hostaddr(str, family)))
- return syntax_err("plain IP address must be supplied: "
- "%s", str);
- break;
- case IPADDR_NET:
- if (!cidr_separator(str) || range_separator(str))
- return syntax_err("IP/netblock must be supplied: %s",
- str);
- break;
- case IPADDR_RANGE:
- if (!range_separator(str) || cidr_separator(str))
- return syntax_err("IP-IP range must supplied: %s",
- str);
- break;
- case IPADDR_ANY:
- default:
- break;
- }
-
- return parse_ipaddr(session, opt, str, family);
-}
-
-/**
- * ipset_parse_ip - parse IPv4|IPv6 address, range or netblock
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- *
- * Parse string as an IPv4|IPv6 address or address range
- * or netblock. Hostnames are resolved. If family is not set
- * yet in the data blob, INET is assumed.
- * The values are stored in the data blob of the session.
- *
- * FIXME: if the hostname resolves to multiple addresses,
- * the first one is used only.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_ip(struct ipset_session *session,
- enum ipset_opt opt, const char *str)
-{
- assert(session);
- assert(opt == IPSET_OPT_IP || opt == IPSET_OPT_IP2);
- assert(str);
-
- return parse_ip(session, opt, str, IPADDR_ANY);
-}
-
-/**
- * ipset_parse_single_ip - parse a single IPv4|IPv6 address
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- *
- * Parse string as an IPv4|IPv6 address or hostname. If family
- * is not set yet in the data blob, INET is assumed.
- * The value is stored in the data blob of the session.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_single_ip(struct ipset_session *session,
- enum ipset_opt opt, const char *str)
-{
- assert(session);
- assert(opt == IPSET_OPT_IP ||
- opt == IPSET_OPT_IP_TO ||
- opt == IPSET_OPT_IP2);
- assert(str);
-
- return parse_ip(session, opt, str, IPADDR_PLAIN);
-}
-
-/**
- * ipset_parse_net - parse IPv4|IPv6 address/cidr
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- *
- * Parse string as an IPv4|IPv6 address/cidr pattern. If family
- * is not set yet in the data blob, INET is assumed.
- * The value is stored in the data blob of the session.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_net(struct ipset_session *session,
- enum ipset_opt opt, const char *str)
-{
- assert(session);
- assert(opt == IPSET_OPT_IP || opt == IPSET_OPT_IP2);
- assert(str);
-
- return parse_ip(session, opt, str, IPADDR_NET);
-}
-
-/**
- * ipset_parse_range - parse IPv4|IPv6 ranges
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- *
- * Parse string as an IPv4|IPv6 range separated by a dash. If family
- * is not set yet in the data blob, INET is assumed.
- * The values are stored in the data blob of the session.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_range(struct ipset_session *session,
- enum ipset_opt opt ASSERT_UNUSED, const char *str)
-{
- assert(session);
- assert(opt == IPSET_OPT_IP || opt == IPSET_OPT_IP2);
- assert(str);
-
- return parse_ip(session, IPSET_OPT_IP, str, IPADDR_RANGE);
-}
-
-/**
- * ipset_parse_netrange - parse IPv4|IPv6 address/cidr or range
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- *
- * Parse string as an IPv4|IPv6 address/cidr pattern or a range
- * of addresses separated by a dash. If family is not set yet in
- * the data blob, INET is assumed.
- * The value is stored in the data blob of the session.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_netrange(struct ipset_session *session,
- enum ipset_opt opt, const char *str)
-{
- assert(session);
- assert(opt == IPSET_OPT_IP || opt == IPSET_OPT_IP2);
- assert(str);
-
- if (!(range_separator(str) || cidr_separator(str)))
- return syntax_err("IP/cidr or IP-IP range must be specified: "
- "%s", str);
- return parse_ip(session, opt, str, IPADDR_ANY);
-}
-
-/**
- * ipset_parse_iprange - parse IPv4|IPv6 address or range
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- *
- * Parse string as an IPv4|IPv6 address pattern or a range
- * of addresses separated by a dash. If family is not set yet in
- * the data blob, INET is assumed.
- * The value is stored in the data blob of the session.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_iprange(struct ipset_session *session,
- enum ipset_opt opt, const char *str)
-{
- assert(session);
- assert(opt == IPSET_OPT_IP || opt == IPSET_OPT_IP2);
- assert(str);
-
- if (cidr_separator(str))
- return syntax_err("IP address or IP-IP range must be "
- "specified: %s", str);
- return parse_ip(session, opt, str, IPADDR_ANY);
-}
-
-/**
- * ipset_parse_ipnet - parse IPv4|IPv6 address or address/cidr pattern
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- *
- * Parse string as an IPv4|IPv6 address or address/cidr pattern.
- * If family is not set yet in the data blob, INET is assumed.
- * The value is stored in the data blob of the session.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_ipnet(struct ipset_session *session,
- enum ipset_opt opt, const char *str)
-{
- assert(session);
- assert(opt == IPSET_OPT_IP || opt == IPSET_OPT_IP2);
- assert(str);
-
- if (range_separator(str))
- return syntax_err("IP address or IP/cidr must be specified: %s",
- str);
- return parse_ip(session, opt, str, IPADDR_ANY);
-}
-
-/**
- * ipset_parse_ip4_single6 - parse IPv4 address, range or netblock or IPv6 address
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- *
- * Parse string as an IPv4 address or address range
- * or netblock or and IPv6 address. Hostnames are resolved. If family
- * is not set yet in the data blob, INET is assumed.
- * The values are stored in the data blob of the session.
- *
- * FIXME: if the hostname resolves to multiple addresses,
- * the first one is used only.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_ip4_single6(struct ipset_session *session,
- enum ipset_opt opt, const char *str)
-{
- struct ipset_data *data;
- uint8_t family;
-
- assert(session);
- assert(opt == IPSET_OPT_IP || opt == IPSET_OPT_IP2);
- assert(str);
-
- data = ipset_session_data(session);
- family = ipset_data_family(data);
-
- if (family == NFPROTO_UNSPEC) {
- family = NFPROTO_IPV4;
- ipset_data_set(data, IPSET_OPT_FAMILY, &family);
- }
-
- return family == NFPROTO_IPV4 ? ipset_parse_ip(session, opt, str)
- : ipset_parse_single_ip(session, opt, str);
-
-}
-
-/**
- * ipset_parse_ip4_net6 - parse IPv4|IPv6 address or address/cidr pattern
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- *
- * Parse string as an IPv4|IPv6 address or address/cidr pattern. For IPv4,
- * address range is valid too.
- * If family is not set yet in the data blob, INET is assumed.
- * The values are stored in the data blob of the session.
- *
- * FIXME: if the hostname resolves to multiple addresses,
- * the first one is used only.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_ip4_net6(struct ipset_session *session,
- enum ipset_opt opt, const char *str)
-{
- struct ipset_data *data;
- uint8_t family;
-
- assert(session);
- assert(opt == IPSET_OPT_IP || opt == IPSET_OPT_IP2);
- assert(str);
-
- data = ipset_session_data(session);
- family = ipset_data_family(data);
-
- if (family == NFPROTO_UNSPEC) {
- family = NFPROTO_IPV4;
- ipset_data_set(data, IPSET_OPT_FAMILY, &family);
- }
-
- return family == NFPROTO_IPV4 ? parse_ip(session, opt, str, IPADDR_ANY)
- : ipset_parse_ipnet(session, opt, str);
-
-}
-
-/**
- * ipset_parse_iptimeout - parse IPv4|IPv6 address and timeout
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- *
- * Parse string as an IPv4|IPv6 address and timeout parameter.
- * If family is not set yet in the data blob, INET is assumed.
- * The value is stored in the data blob of the session.
- *
- * Compatibility parser.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_iptimeout(struct ipset_session *session,
- enum ipset_opt opt, const char *str)
-{
- char *tmp, *saved, *a;
- int err;
-
- assert(session);
- assert(opt == IPSET_OPT_IP);
- assert(str);
-
- /* IP,timeout */
- if (ipset_data_flags_test(ipset_session_data(session),
- IPSET_FLAG(IPSET_OPT_TIMEOUT)))
- return syntax_err("mixed syntax, timeout already specified");
-
- tmp = saved = strdup(str);
- if (saved == NULL)
- return ipset_err(session,
- "Cannot allocate memory to duplicate %s.",
- str);
-
- a = elem_separator(tmp);
- if (a == NULL) {
- free(saved);
- return syntax_err("Missing separator from %s", str);
- }
- *a++ = '\0';
- err = parse_ip(session, opt, tmp, IPADDR_ANY);
- if (!err)
- err = ipset_parse_uint32(session, IPSET_OPT_TIMEOUT, a);
-
- free(saved);
- return err;
-}
-
-#define check_setname(str, saved) \
-do { \
- if (strlen(str) > IPSET_MAXNAMELEN - 1) { \
- if (saved != NULL) \
- free(saved); \
- return syntax_err("setname '%s' is longer than %u characters",\
- str, IPSET_MAXNAMELEN - 1); \
- } \
-} while (0)
-
-
-/**
- * ipset_parse_name_compat - parse setname as element
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- *
- * Parse string as a setname or a setname element to add to a set.
- * The pattern "setname,before|after,setname" is recognized and
- * parsed.
- * The value is stored in the data blob of the session.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_name_compat(struct ipset_session *session,
- enum ipset_opt opt, const char *str)
-{
- char *saved;
- char *a = NULL, *b = NULL, *tmp;
- int err, before = 0;
- const char *sep = IPSET_ELEM_SEPARATOR;
- struct ipset_data *data;
-
- assert(session);
- assert(opt == IPSET_OPT_NAME);
- assert(str);
-
- data = ipset_session_data(session);
- if (ipset_data_flags_test(data, IPSET_FLAG(IPSET_OPT_NAMEREF)))
- syntax_err("mixed syntax, before|after option already used");
-
- tmp = saved = strdup(str);
- if (saved == NULL)
- return ipset_err(session,
- "Cannot allocate memory to duplicate %s.",
- str);
- if ((a = elem_separator(tmp)) != NULL) {
- /* setname,[before|after,setname */
- *a++ = '\0';
- if ((b = elem_separator(a)) != NULL)
- *b++ = '\0';
- if (b == NULL ||
- !(STREQ(a, "before") || STREQ(a, "after"))) {
- err = ipset_err(session, "you must specify elements "
- "as setname%s[before|after]%ssetname",
- sep, sep);
- goto out;
- }
- before = STREQ(a, "before");
- }
- check_setname(tmp, saved);
- if ((err = ipset_data_set(data, opt, tmp)) != 0 || b == NULL)
- goto out;
-
- check_setname(b, saved);
- if ((err = ipset_data_set(data,
- IPSET_OPT_NAMEREF, b)) != 0)
- goto out;
-
- if (before)
- err = ipset_data_set(data, IPSET_OPT_BEFORE, &before);
-
-out:
- free(saved);
- return err;
-}
-
-/**
- * ipset_parse_setname - parse string as a setname
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- *
- * Parse string as a setname.
- * The value is stored in the data blob of the session.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_setname(struct ipset_session *session,
- enum ipset_opt opt, const char *str)
-{
- assert(session);
- assert(opt == IPSET_SETNAME ||
- opt == IPSET_OPT_NAME ||
- opt == IPSET_OPT_SETNAME2);
- assert(str);
-
- check_setname(str, NULL);
-
- return ipset_session_data_set(session, opt, str);
-}
-
-/**
- * ipset_parse_before - parse string as "before" reference setname
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- *
- * Parse string as a "before" reference setname for list:set
- * type of sets. The value is stored in the data blob of the session.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_before(struct ipset_session *session,
- enum ipset_opt opt, const char *str)
-{
- struct ipset_data *data;
-
- assert(session);
- assert(opt == IPSET_OPT_NAMEREF);
- assert(str);
-
- data = ipset_session_data(session);
- if (ipset_data_flags_test(data, IPSET_FLAG(IPSET_OPT_NAMEREF)))
- syntax_err("mixed syntax, before|after option already used");
-
- check_setname(str, NULL);
- ipset_data_set(data, IPSET_OPT_BEFORE, str);
-
- return ipset_data_set(data, opt, str);
-}
-
-/**
- * ipset_parse_after - parse string as "after" reference setname
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- *
- * Parse string as a "after" reference setname for list:set
- * type of sets. The value is stored in the data blob of the session.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_after(struct ipset_session *session,
- enum ipset_opt opt, const char *str)
-{
- struct ipset_data *data;
-
- assert(session);
- assert(opt == IPSET_OPT_NAMEREF);
- assert(str);
-
- data = ipset_session_data(session);
- if (ipset_data_flags_test(data, IPSET_FLAG(IPSET_OPT_NAMEREF)))
- syntax_err("mixed syntax, before|after option already used");
-
- check_setname(str, NULL);
-
- return ipset_data_set(data, opt, str);
-}
-
-/**
- * ipset_parse_uint32 - parse string as an unsigned integer
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- *
- * Parse string as an unsigned integer number.
- * The value is stored in the data blob of the session.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_uint32(struct ipset_session *session,
- enum ipset_opt opt, const char *str)
-{
- uint32_t value;
- int err;
-
- assert(session);
- assert(str);
-
- if ((err = string_to_u32(session, str, &value)) == 0)
- return ipset_session_data_set(session, opt, &value);
-
- return err;
-}
-
-/**
- * ipset_parse_uint8 - parse string as an unsigned short integer
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- *
- * Parse string as an unsigned short integer number.
- * The value is stored in the data blob of the session.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_uint8(struct ipset_session *session,
- enum ipset_opt opt, const char *str)
-{
- uint8_t value;
- int err;
-
- assert(session);
- assert(str);
-
- if ((err = string_to_u8(session, str, &value)) == 0)
- return ipset_session_data_set(session, opt, &value);
-
- return err;
-}
-
-/**
- * ipset_parse_netmask - parse string as a CIDR netmask value
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- *
- * Parse string as a CIDR netmask value, depending on family type.
- * If family is not set yet, INET is assumed.
- * The value is stored in the data blob of the session.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_netmask(struct ipset_session *session,
- enum ipset_opt opt, const char *str)
-{
- uint8_t family, cidr;
- struct ipset_data *data;
- int err = 0;
-
- assert(session);
- assert(opt == IPSET_OPT_NETMASK);
- assert(str);
-
- data = ipset_session_data(session);
- family = ipset_data_family(data);
- if (family == NFPROTO_UNSPEC) {
- family = NFPROTO_IPV4;
- ipset_data_set(data, IPSET_OPT_FAMILY, &family);
- }
-
- err = string_to_cidr(session, str,
- family == NFPROTO_IPV4 ? 1 : 4,
- family == NFPROTO_IPV4 ? 31 : 124,
- &cidr);
-
- if (err)
- return syntax_err("netmask is out of the inclusive range "
- "of %u-%u",
- family == NFPROTO_IPV4 ? 1 : 4,
- family == NFPROTO_IPV4 ? 31 : 124);
-
- return ipset_data_set(data, opt, &cidr);
-}
-
-/**
- * ipset_parse_flag - "parse" option flags
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- *
- * Parse option flags :-)
- * The value is stored in the data blob of the session.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_flag(struct ipset_session *session,
- enum ipset_opt opt, const char *str UNUSED)
-{
- assert(session);
-
- return ipset_session_data_set(session, opt, NULL);
-}
-
-/**
- * ipset_parse_type - parse ipset type name
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- *
- * Parse ipset module type: supports both old and new formats.
- * The type name is looked up and the type found is stored
- * in the data blob of the session.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_typename(struct ipset_session *session,
- enum ipset_opt opt ASSERT_UNUSED, const char *str)
-{
- const struct ipset_type *type;
- const char *typename;
-
- assert(session);
- assert(opt == IPSET_OPT_TYPENAME);
- assert(str);
-
- if (strlen(str) > IPSET_MAXNAMELEN - 1)
- return syntax_err("typename '%s' is longer than %u characters",
- str, IPSET_MAXNAMELEN - 1);
-
- /* Find the corresponding type */
- typename = ipset_typename_resolve(str);
- if (typename == NULL)
- return syntax_err("typename '%s' is unkown", str);
- ipset_session_data_set(session, IPSET_OPT_TYPENAME, typename);
- type = ipset_type_get(session, IPSET_CMD_CREATE);
-
- if (type == NULL)
- return -1;
-
- return ipset_session_data_set(session, IPSET_OPT_TYPE, type);
-}
-
-/**
- * ipset_parse_iface - parse string as an interface name
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- *
- * Parse string as an interface name, optionally with 'physdev:' prefix.
- * The value is stored in the data blob of the session.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_iface(struct ipset_session *session,
- enum ipset_opt opt, const char *str)
-{
- struct ipset_data *data;
- int offset = 0, err = 0;
-
- assert(session);
- assert(opt == IPSET_OPT_IFACE);
- assert(str);
-
- data = ipset_session_data(session);
- if (STREQ(str, "physdev:")) {
- offset = 8;
- err = ipset_data_set(data, IPSET_OPT_PHYSDEV, str);
- }
- if (strlen(str + offset) > IFNAMSIZ - 1)
- return syntax_err("interface name '%s' is longer "
- "than %u characters",
- str + offset, IFNAMSIZ - 1);
-
- return ipset_data_set(data, opt, str + offset);
-}
-
-/**
- * ipset_parse_output - parse output format name
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- *
- * Parse output format names and set session mode.
- * The value is stored in the session.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_output(struct ipset_session *session,
- int opt UNUSED, const char *str)
-{
- assert(session);
- assert(str);
-
- if (STREQ(str, "plain"))
- return ipset_session_output(session, IPSET_LIST_PLAIN);
- else if (STREQ(str, "xml"))
- return ipset_session_output(session, IPSET_LIST_XML);
- else if (STREQ(str, "save"))
- return ipset_session_output(session, IPSET_LIST_SAVE);
-
- return syntax_err("unkown output mode '%s'", str);
-}
-
-/**
- * ipset_parse_ignored - "parse" ignored option
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- *
- * Ignore deprecated options. A single warning is generated
- * for every ignored opton.
- *
- * Returns 0.
- */
-int
-ipset_parse_ignored(struct ipset_session *session,
- enum ipset_opt opt, const char *str)
-{
- assert(session);
- assert(str);
-
- if (!ipset_data_ignored(ipset_session_data(session), opt))
- ipset_warn(session,
- "Option %s is ignored. "
- "Please upgrade your syntax.", str);
-
- return 0;
-}
-
-/**
- * ipset_call_parser - call a parser function
- * @session: session structure
- * @parsefn: parser function
- * @optstr: option name
- * @opt: option kind of the data
- * @str: string to parse
- *
- * Wrapper to call the parser functions so that ignored options
- * are handled properly.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_call_parser(struct ipset_session *session,
- const struct ipset_arg *arg,
- const char *str)
-{
- if (ipset_data_flags_test(ipset_session_data(session),
- IPSET_FLAG(arg->opt)))
- syntax_err("%s already specified", arg->name[0]);
-
- return arg->parse(session, arg->opt, str);
-}
-
-#define parse_elem(s, t, d, str) \
-do { \
- if (!(t)->elem[d - 1].parse) \
- goto internal; \
- ret = (t)->elem[d - 1].parse(s, (t)->elem[d - 1].opt, str); \
- if (ret) \
- goto out; \
-} while (0)
-
-#define elem_syntax_err(fmt, args...) \
-do { \
- free(saved); \
- return syntax_err(fmt , ## args);\
-} while (0)
-
-/**
- * ipset_parse_elem - parse ADT elem, depending on settype
- * @session: session structure
- * @opt: option kind of the data
- * @str: string to parse
- *
- * Parse string as a (multipart) element according to the settype.
- * The value is stored in the data blob of the session.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_elem(struct ipset_session *session,
- enum ipset_opt optional, const char *str)
-{
- const struct ipset_type *type;
- char *a = NULL, *b = NULL, *tmp, *saved;
- int ret;
-
- assert(session);
- assert(str);
-
- type = ipset_session_data_get(session, IPSET_OPT_TYPE);
- if (!type)
- return ipset_err(session,
- "Internal error: set type is unknown!");
-
- saved = tmp = strdup(str);
- if (tmp == NULL)
- return ipset_err(session,
- "Cannot allocate memory to duplicate %s.",
- str);
-
- a = elem_separator(tmp);
- if (type->dimension > IPSET_DIM_ONE) {
- if (a != NULL) {
- /* elem,elem */
- *a++ = '\0';
- } else if (!optional)
- elem_syntax_err("Second element is missing from %s.",
- str);
- } else if (a != NULL) {
- if (type->compat_parse_elem) {
- ret = type->compat_parse_elem(session,
- type->elem[IPSET_DIM_ONE - 1].opt,
- saved);
- goto out;
- }
- elem_syntax_err("Elem separator in %s, "
- "but settype %s supports none.",
- str, type->name);
- }
-
- if (a)
- b = elem_separator(a);
- if (type->dimension > IPSET_DIM_TWO) {
- if (b != NULL) {
- /* elem,elem,elem */
- *b++ = '\0';
- } else if (!optional)
- elem_syntax_err("Third element is missing from %s.",
- str);
- } else if (b != NULL)
- elem_syntax_err("Two elem separators in %s, "
- "but settype %s supports one.",
- str, type->name);
- if (b != NULL && elem_separator(b))
- elem_syntax_err("Three elem separators in %s, "
- "but settype %s supports two.",
- str, type->name);
-
- D("parse elem part one: %s", tmp);
- parse_elem(session, type, IPSET_DIM_ONE, tmp);
-
- if (type->dimension > IPSET_DIM_ONE && a != NULL) {
- D("parse elem part two: %s", a);
- parse_elem(session, type, IPSET_DIM_TWO, a);
- }
- if (type->dimension > IPSET_DIM_TWO && b != NULL)
- parse_elem(session, type, IPSET_DIM_THREE, b);
-
- goto out;
-
-internal:
- ret = ipset_err(session,
- "Internal error: missing parser function for %s",
- type->name);
-out:
- free(saved);
- return ret;
-}
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <assert.h> /* assert */
-#include <errno.h> /* errno */
-#include <stdio.h> /* snprintf */
-#include <netdb.h> /* getservbyport */
-#include <sys/types.h> /* inet_ntop */
-#include <sys/socket.h> /* inet_ntop */
-#include <arpa/inet.h> /* inet_ntop */
-#include <net/ethernet.h> /* ETH_ALEN */
-#include <net/if.h> /* IFNAMSIZ */
-
-#include <libipset/debug.h> /* D() */
-#include <libipset/data.h> /* ipset_data_* */
-#include <libipset/icmp.h> /* icmp_to_name */
-#include <libipset/icmpv6.h> /* icmpv6_to_name */
-#include <libipset/parse.h> /* IPSET_*_SEPARATOR */
-#include <libipset/types.h> /* ipset set types */
-#include <libipset/session.h> /* IPSET_FLAG_ */
-#include <libipset/utils.h> /* UNUSED */
-#include <libipset/ui.h> /* IPSET_ENV_* */
-#include <libipset/print.h> /* prototypes */
-
-/* Print data (to output buffer). All function must follow snprintf. */
-
-#define SNPRINTF_FAILURE(size, len, offset) \
-do { \
- if (size < 0 || (unsigned int) size >= len) \
- return size; \
- offset += size; \
- len -= size; \
-} while (0)
-
-/**
- * ipset_print_ether - print ethernet address to string
- * @buf: printing buffer
- * @len: length of available buffer space
- * @data: data blob
- * @opt: the option kind
- * @env: environment flags
- *
- * Print Ethernet address to output buffer.
- *
- * Return lenght of printed string or error size.
- */
-int
-ipset_print_ether(char *buf, unsigned int len,
- const struct ipset_data *data, enum ipset_opt opt,
- uint8_t env UNUSED)
-{
- const unsigned char *ether;
- int i, size, offset = 0;
-
- assert(buf);
- assert(len > 0);
- assert(data);
- assert(opt == IPSET_OPT_ETHER);
-
- if (len < ETH_ALEN*3)
- return -1;
-
- ether = ipset_data_get(data, opt);
- assert(ether);
-
- size = snprintf(buf, len, "%02X", ether[0]);
- SNPRINTF_FAILURE(size, len, offset);
- for (i = 1; i < ETH_ALEN; i++) {
- size = snprintf(buf + offset, len, ":%02X", ether[i]);
- SNPRINTF_FAILURE(size, len, offset);
- }
-
- return offset;
-}
-
-/**
- * ipset_print_family - print INET family
- * @buf: printing buffer
- * @len: length of available buffer space
- * @data: data blob
- * @opt: the option kind
- * @env: environment flags
- *
- * Print INET family string to output buffer.
- *
- * Return lenght of printed string or error size.
- */
-int
-ipset_print_family(char *buf, unsigned int len,
- const struct ipset_data *data,
- enum ipset_opt opt ASSERT_UNUSED,
- uint8_t env UNUSED)
-{
- uint8_t family;
-
- assert(buf);
- assert(len > 0);
- assert(data);
- assert(opt == IPSET_OPT_FAMILY);
-
- if (len < strlen("inet6") + 1)
- return -1;
-
- family = ipset_data_family(data);
-
- return snprintf(buf, len, "%s",
- family == AF_INET ? "inet" :
- family == AF_INET6 ? "inet6" : "any");
-}
-
-/**
- * ipset_print_type - print ipset type string
- * @buf: printing buffer
- * @len: length of available buffer space
- * @data: data blob
- * @opt: the option kind
- * @env: environment flags
- *
- * Print ipset module string identifier to output buffer.
- *
- * Return lenght of printed string or error size.
- */
-int
-ipset_print_type(char *buf, unsigned int len,
- const struct ipset_data *data, enum ipset_opt opt,
- uint8_t env UNUSED)
-{
- const struct ipset_type *type;
-
- assert(buf);
- assert(len > 0);
- assert(data);
- assert(opt == IPSET_OPT_TYPE);
-
- type = ipset_data_get(data, opt);
- assert(type);
- if (len < strlen(type->name) + 1)
- return -1;
-
- return snprintf(buf, len, "%s", type->name);
-}
-
-static inline int
-__getnameinfo4(char *buf, unsigned int len,
- int flags, const union nf_inet_addr *addr)
-{
- struct sockaddr_in saddr;
- int err;
-
- memset(&saddr, 0, sizeof(saddr));
- in4cpy(&saddr.sin_addr, &addr->in);
- saddr.sin_family = NFPROTO_IPV4;
-
- err = getnameinfo((const struct sockaddr *)&saddr,
- sizeof(saddr),
- buf, len, NULL, 0, flags);
-
- if (!(flags & NI_NUMERICHOST) &&
- (err == EAI_AGAIN || (err == 0 && strchr(buf, '-') != NULL)))
- err = getnameinfo((const struct sockaddr *)&saddr,
- sizeof(saddr),
- buf, len, NULL, 0,
- flags | NI_NUMERICHOST);
- D("getnameinfo err: %i, errno %i", err, errno);
- return (err == 0 ? (int)strlen(buf) :
- (err == EAI_OVERFLOW || err == EAI_SYSTEM) ? (int)len : -1);
-}
-
-static inline int
-__getnameinfo6(char *buf, unsigned int len,
- int flags, const union nf_inet_addr *addr)
-{
- struct sockaddr_in6 saddr;
- int err;
-
- memset(&saddr, 0, sizeof(saddr));
- in6cpy(&saddr.sin6_addr, &addr->in6);
- saddr.sin6_family = NFPROTO_IPV6;
-
- err = getnameinfo((const struct sockaddr *)&saddr,
- sizeof(saddr),
- buf, len, NULL, 0, flags);
-
- if (!(flags & NI_NUMERICHOST) &&
- (err == EAI_AGAIN || (err == 0 && strchr(buf, '-') != NULL)))
- err = getnameinfo((const struct sockaddr *)&saddr,
- sizeof(saddr),
- buf, len, NULL, 0,
- flags | NI_NUMERICHOST);
- D("getnameinfo err: %i, errno %i", err, errno);
- return (err == 0 ? (int)strlen(buf) :
- (err == EAI_OVERFLOW || err == EAI_SYSTEM) ? (int)len : -1);
-}
-
-#define SNPRINTF_IP(mask, f) \
-static int \
-snprintf_ipv##f(char *buf, unsigned int len, int flags, \
- const union nf_inet_addr *ip, uint8_t cidr) \
-{ \
- int size, offset = 0; \
- \
- size = __getnameinfo##f(buf, len, flags, ip); \
- SNPRINTF_FAILURE(size, len, offset); \
- \
- D("cidr %u mask %u", cidr, mask); \
- if (cidr == mask) \
- return offset; \
- D("print cidr"); \
- size = snprintf(buf + offset, len, \
- "%s%u", IPSET_CIDR_SEPARATOR, cidr); \
- SNPRINTF_FAILURE(size, len, offset); \
- return offset; \
-}
-
-SNPRINTF_IP(32, 4)
-
-SNPRINTF_IP(128, 6)
-
-/**
- * ipset_print_ip - print IPv4|IPv6 address to string
- * @buf: printing buffer
- * @len: length of available buffer space
- * @data: data blob
- * @opt: the option kind
- * @env: environment flags
- *
- * Print IPv4|IPv6 address, address/cidr or address range to output buffer.
- *
- * Return lenght of printed string or error size.
- */
-int
-ipset_print_ip(char *buf, unsigned int len,
- const struct ipset_data *data, enum ipset_opt opt,
- uint8_t env)
-{
- const union nf_inet_addr *ip;
- uint8_t family, cidr;
- int flags, size, offset = 0;
- enum ipset_opt cidropt;
-
- assert(buf);
- assert(len > 0);
- assert(data);
- assert(opt == IPSET_OPT_IP || opt == IPSET_OPT_IP2);
-
- D("len: %u", len);
- family = ipset_data_family(data);
- cidropt = opt == IPSET_OPT_IP ? IPSET_OPT_CIDR : IPSET_OPT_CIDR2;
- if (ipset_data_test(data, cidropt)) {
- cidr = *(const uint8_t *) ipset_data_get(data, cidropt);
- D("CIDR: %u", cidr);
- } else
- cidr = family == NFPROTO_IPV6 ? 128 : 32;
- flags = (env & IPSET_ENV_RESOLVE) ? 0 : NI_NUMERICHOST;
-
- ip = ipset_data_get(data, opt);
- assert(ip);
- if (family == NFPROTO_IPV4)
- size = snprintf_ipv4(buf, len, flags, ip, cidr);
- else if (family == NFPROTO_IPV6)
- size = snprintf_ipv6(buf, len, flags, ip, cidr);
- else
- return -1;
- D("size %i, len %u", size, len);
- SNPRINTF_FAILURE(size, len, offset);
-
- D("len: %u, offset %u", len, offset);
- if (!ipset_data_test(data, IPSET_OPT_IP_TO))
- return offset;
-
- size = snprintf(buf + offset, len, "%s", IPSET_RANGE_SEPARATOR);
- SNPRINTF_FAILURE(size, len, offset);
-
- ip = ipset_data_get(data, IPSET_OPT_IP_TO);
- if (family == NFPROTO_IPV4)
- size = snprintf_ipv4(buf + offset, len, flags, ip, cidr);
- else if (family == NFPROTO_IPV6)
- size = snprintf_ipv6(buf + offset, len, flags, ip, cidr);
- else
- return -1;
-
- SNPRINTF_FAILURE(size, len, offset);
- return offset;
-}
-
-/**
- * ipset_print_ipaddr - print IPv4|IPv6 address to string
- * @buf: printing buffer
- * @len: length of available buffer space
- * @data: data blob
- * @opt: the option kind
- * @env: environment flags
- *
- * Print IPv4|IPv6 address or address/cidr to output buffer.
- *
- * Return lenght of printed string or error size.
- */
-int
-ipset_print_ipaddr(char *buf, unsigned int len,
- const struct ipset_data *data, enum ipset_opt opt,
- uint8_t env)
-{
- const union nf_inet_addr *ip;
- uint8_t family, cidr;
- enum ipset_opt cidropt;
- int flags;
-
- assert(buf);
- assert(len > 0);
- assert(data);
- assert(opt == IPSET_OPT_IP ||
- opt == IPSET_OPT_IP_TO ||
- opt == IPSET_OPT_IP2);
-
- family = ipset_data_family(data);
- cidropt = opt == IPSET_OPT_IP ? IPSET_OPT_CIDR : IPSET_OPT_CIDR2;
- if (ipset_data_test(data, cidropt))
- cidr = *(const uint8_t *) ipset_data_get(data, cidropt);
- else
- cidr = family == NFPROTO_IPV6 ? 128 : 32;
- flags = (env & IPSET_ENV_RESOLVE) ? 0 : NI_NUMERICHOST;
-
- ip = ipset_data_get(data, opt);
- assert(ip);
- if (family == NFPROTO_IPV4)
- return snprintf_ipv4(buf, len, flags, ip, cidr);
- else if (family == NFPROTO_IPV6)
- return snprintf_ipv6(buf, len, flags, ip, cidr);
-
- return -1;
-}
-
-/**
- * ipset_print_number - print number to string
- * @buf: printing buffer
- * @len: length of available buffer space
- * @data: data blob
- * @opt: the option kind
- * @env: environment flags
- *
- * Print number to output buffer.
- *
- * Return lenght of printed string or error size.
- */
-int
-ipset_print_number(char *buf, unsigned int len,
- const struct ipset_data *data, enum ipset_opt opt,
- uint8_t env UNUSED)
-{
- size_t maxsize;
- const void *number;
-
- assert(buf);
- assert(len > 0);
- assert(data);
-
- number = ipset_data_get(data, opt);
- maxsize = ipset_data_sizeof(opt, AF_INET);
- D("opt: %u, maxsize %zu", opt, maxsize);
- if (maxsize == sizeof(uint8_t))
- return snprintf(buf, len, "%u", *(const uint8_t *) number);
- else if (maxsize == sizeof(uint16_t))
- return snprintf(buf, len, "%u", *(const uint16_t *) number);
- else if (maxsize == sizeof(uint32_t))
- return snprintf(buf, len, "%lu",
- (long unsigned) *(const uint32_t *) number);
- else
- assert(0);
- return 0;
-}
-
-/**
- * ipset_print_name - print setname element string
- * @buf: printing buffer
- * @len: length of available buffer space
- * @data: data blob
- * @opt: the option kind
- * @env: environment flags
- *
- * Print setname element string to output buffer.
- *
- * Return lenght of printed string or error size.
- */
-int
-ipset_print_name(char *buf, unsigned int len,
- const struct ipset_data *data, enum ipset_opt opt,
- uint8_t env UNUSED)
-{
- const char *name;
- int size, offset = 0;
-
- assert(buf);
- assert(len > 0);
- assert(data);
- assert(opt == IPSET_OPT_NAME);
-
- if (len < 2*IPSET_MAXNAMELEN + 2 + strlen("before"))
- return -1;
-
- name = ipset_data_get(data, opt);
- assert(name);
- size = snprintf(buf, len, "%s", name);
- SNPRINTF_FAILURE(size, len, offset);
-
- if (ipset_data_test(data, IPSET_OPT_NAMEREF)) {
- bool before = false;
- if (ipset_data_flags_test(data, IPSET_FLAG(IPSET_OPT_FLAGS))) {
- const uint32_t *flags =
- ipset_data_get(data, IPSET_OPT_FLAGS);
- before = (*flags) & IPSET_FLAG_BEFORE;
- }
- size = snprintf(buf + offset, len,
- " %s %s", before ? "before" : "after",
- (const char *) ipset_data_get(data,
- IPSET_OPT_NAMEREF));
- SNPRINTF_FAILURE(size, len, offset);
- }
-
- return offset;
-}
-
-/**
- * ipset_print_port - print port or port range
- * @buf: printing buffer
- * @len: length of available buffer space
- * @data: data blob
- * @opt: the option kind
- * @env: environment flags
- *
- * Print port or port range to output buffer.
- *
- * Return lenght of printed string or error size.
- */
-int
-ipset_print_port(char *buf, unsigned int len,
- const struct ipset_data *data,
- enum ipset_opt opt ASSERT_UNUSED,
- uint8_t env UNUSED)
-{
- const uint16_t *port;
- int size, offset = 0;
-
- assert(buf);
- assert(len > 0);
- assert(data);
- assert(opt == IPSET_OPT_PORT);
-
- if (len < 2*strlen("65535") + 2)
- return -1;
-
- port = ipset_data_get(data, IPSET_OPT_PORT);
- assert(port);
- size = snprintf(buf, len, "%u", *port);
- SNPRINTF_FAILURE(size, len, offset);
-
- if (ipset_data_test(data, IPSET_OPT_PORT_TO)) {
- port = ipset_data_get(data, IPSET_OPT_PORT_TO);
- size = snprintf(buf + offset, len,
- "%s%u",
- IPSET_RANGE_SEPARATOR, *port);
- SNPRINTF_FAILURE(size, len, offset);
- }
-
- return offset;
-}
-
-/**
- * ipset_print_iface - print interface element string
- * @buf: printing buffer
- * @len: length of available buffer space
- * @data: data blob
- * @opt: the option kind
- * @env: environment flags
- *
- * Print interface element string to output buffer.
- *
- * Return lenght of printed string or error size.
- */
-int
-ipset_print_iface(char *buf, unsigned int len,
- const struct ipset_data *data, enum ipset_opt opt,
- uint8_t env UNUSED)
-{
- const char *name;
- int size, offset = 0;
-
- assert(buf);
- assert(len > 0);
- assert(data);
- assert(opt == IPSET_OPT_IFACE);
-
- if (len < IFNAMSIZ + strlen("physdev:"))
- return -1;
-
- if (ipset_data_test(data, IPSET_OPT_PHYSDEV)) {
- size = snprintf(buf, len, "physdev:");
- SNPRINTF_FAILURE(size, len, offset);
- }
- name = ipset_data_get(data, opt);
- assert(name);
- size = snprintf(buf, len, "%s", name);
- SNPRINTF_FAILURE(size, len, offset);
- return offset;
-}
-
-/**
- * ipset_print_proto - print protocol name
- * @buf: printing buffer
- * @len: length of available buffer space
- * @data: data blob
- * @opt: the option kind
- * @env: environment flags
- *
- * Print protocol name to output buffer.
- *
- * Return lenght of printed string or error size.
- */
-int
-ipset_print_proto(char *buf, unsigned int len,
- const struct ipset_data *data,
- enum ipset_opt opt ASSERT_UNUSED,
- uint8_t env UNUSED)
-{
- const struct protoent *protoent;
- uint8_t proto;
-
- assert(buf);
- assert(len > 0);
- assert(data);
- assert(opt == IPSET_OPT_PROTO);
-
- proto = *(const uint8_t *) ipset_data_get(data, IPSET_OPT_PROTO);
- assert(proto);
-
- protoent = getprotobynumber(proto);
- if (protoent)
- return snprintf(buf, len, "%s", protoent->p_name);
-
- /* Should not happen */
- return snprintf(buf, len, "%u", proto);
-}
-
-/**
- * ipset_print_icmp - print ICMP code name or type/code
- * @buf: printing buffer
- * @len: length of available buffer space
- * @data: data blob
- * @opt: the option kind
- * @env: environment flags
- *
- * Print ICMP code name or type/code name to output buffer.
- *
- * Return lenght of printed string or error size.
- */
-int
-ipset_print_icmp(char *buf, unsigned int len,
- const struct ipset_data *data,
- enum ipset_opt opt ASSERT_UNUSED,
- uint8_t env UNUSED)
-{
- const char *name;
- uint16_t typecode;
-
- assert(buf);
- assert(len > 0);
- assert(data);
- assert(opt == IPSET_OPT_PORT);
-
- typecode = *(const uint16_t *) ipset_data_get(data, IPSET_OPT_PORT);
- name = icmp_to_name(typecode >> 8, typecode & 0xFF);
- if (name != NULL)
- return snprintf(buf, len, "%s", name);
- else
- return snprintf(buf, len, "%u/%u",
- typecode >> 8, typecode & 0xFF);
-}
-
-/**
- * ipset_print_icmpv6 - print ICMPv6 code name or type/code
- * @buf: printing buffer
- * @len: length of available buffer space
- * @data: data blob
- * @opt: the option kind
- * @env: environment flags
- *
- * Print ICMPv6 code name or type/code name to output buffer.
- *
- * Return lenght of printed string or error size.
- */
-int
-ipset_print_icmpv6(char *buf, unsigned int len,
- const struct ipset_data *data,
- enum ipset_opt opt ASSERT_UNUSED,
- uint8_t env UNUSED)
-{
- const char *name;
- uint16_t typecode;
-
- assert(buf);
- assert(len > 0);
- assert(data);
- assert(opt == IPSET_OPT_PORT);
-
- typecode = *(const uint16_t *) ipset_data_get(data, IPSET_OPT_PORT);
- name = icmpv6_to_name(typecode >> 8, typecode & 0xFF);
- if (name != NULL)
- return snprintf(buf, len, "%s", name);
- else
- return snprintf(buf, len, "%u/%u",
- typecode >> 8, typecode & 0xFF);
-}
-
-/**
- * ipset_print_proto_port - print proto:port
- * @buf: printing buffer
- * @len: length of available buffer space
- * @data: data blob
- * @opt: the option kind
- * @env: environment flags
- *
- * Print protocol and port to output buffer.
- *
- * Return lenght of printed string or error size.
- */
-int
-ipset_print_proto_port(char *buf, unsigned int len,
- const struct ipset_data *data,
- enum ipset_opt opt ASSERT_UNUSED,
- uint8_t env UNUSED)
-{
- int size, offset = 0;
-
- assert(buf);
- assert(len > 0);
- assert(data);
- assert(opt == IPSET_OPT_PORT);
-
- if (ipset_data_flags_test(data, IPSET_FLAG(IPSET_OPT_PROTO))) {
- uint8_t proto = *(const uint8_t *) ipset_data_get(data,
- IPSET_OPT_PROTO);
- size = ipset_print_proto(buf, len, data, IPSET_OPT_PROTO, env);
- SNPRINTF_FAILURE(size, len, offset);
- if (len < 2)
- return -ENOSPC;
- size = snprintf(buf + offset, len, IPSET_PROTO_SEPARATOR);
- SNPRINTF_FAILURE(size, len, offset);
-
- 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,
- IPSET_OPT_PORT, env);
- case IPPROTO_ICMPV6:
- return ipset_print_icmpv6(buf + offset, len, data,
- IPSET_OPT_PORT, env);
- default:
- break;
- }
- }
- size = ipset_print_port(buf + offset, len, data, IPSET_OPT_PORT, env);
- SNPRINTF_FAILURE(size, len, offset);
-
- return offset;
-}
-
-#define print_second(data) \
-ipset_data_flags_test(data, \
- IPSET_FLAG(IPSET_OPT_PORT)|IPSET_FLAG(IPSET_OPT_ETHER))
-
-#define print_third(data) \
-ipset_data_flags_test(data, IPSET_FLAG(IPSET_OPT_IP2))
-
-/**
- * ipset_print_elem - print ADT elem according to settype
- * @buf: printing buffer
- * @len: length of available buffer space
- * @data: data blob
- * @opt: the option kind
- * @env: environment flags
- *
- * Print (multipart) element according to settype
- *
- * Return lenght of printed string or error size.
- */
-int
-ipset_print_elem(char *buf, unsigned int len,
- const struct ipset_data *data, enum ipset_opt opt UNUSED,
- uint8_t env)
-{
- const struct ipset_type *type;
- int size, offset = 0;
-
- assert(buf);
- assert(len > 0);
- assert(data);
-
- type = ipset_data_get(data, IPSET_OPT_TYPE);
- if (!type)
- return -1;
-
- size = type->elem[IPSET_DIM_ONE - 1].print(buf, len, data,
- type->elem[IPSET_DIM_ONE - 1].opt, env);
- SNPRINTF_FAILURE(size, len, offset);
- IF_D(ipset_data_test(data, type->elem[IPSET_DIM_TWO - 1].opt),
- "print second elem");
- if (type->dimension == IPSET_DIM_ONE ||
- (type->last_elem_optional &&
- !ipset_data_test(data, type->elem[IPSET_DIM_TWO - 1].opt)))
- return offset;
-
- size = snprintf(buf + offset, len, IPSET_ELEM_SEPARATOR);
- SNPRINTF_FAILURE(size, len, offset);
- size = type->elem[IPSET_DIM_TWO - 1].print(buf + offset, len, data,
- type->elem[IPSET_DIM_TWO - 1].opt, env);
- SNPRINTF_FAILURE(size, len, offset);
- if (type->dimension == IPSET_DIM_TWO ||
- (type->last_elem_optional &&
- !ipset_data_test(data, type->elem[IPSET_DIM_THREE - 1].opt)))
- return offset;
-
- size = snprintf(buf + offset, len, IPSET_ELEM_SEPARATOR);
- SNPRINTF_FAILURE(size, len, offset);
- size = type->elem[IPSET_DIM_THREE - 1].print(buf + offset, len, data,
- type->elem[IPSET_DIM_THREE - 1].opt, env);
- SNPRINTF_FAILURE(size, len, offset);
-
- return offset;
-}
-
-/**
- * ipset_print_flag - print a flag
- * @buf: printing buffer
- * @len: length of available buffer space
- * @data: data blob
- * @opt: the option kind
- * @env: environment flags
- *
- * Print a flag, i.e. option without value
- *
- * Return lenght of printed string or error size.
- */
-int
-ipset_print_flag(char *buf UNUSED, unsigned int len UNUSED,
- const struct ipset_data *data UNUSED,
- enum ipset_opt opt UNUSED, uint8_t env UNUSED)
-{
- return 0;
-}
-
-/**
- * ipset_print_data - print data, generic fuction
- * @buf: printing buffer
- * @len: length of available buffer space
- * @data: data blob
- * @opt: the option kind
- * @env: environment flags
- *
- * Generic wrapper of the printing functions.
- *
- * Return lenght of printed string or error size.
- */
-int
-ipset_print_data(char *buf, unsigned int len,
- const struct ipset_data *data, enum ipset_opt opt,
- uint8_t env)
-{
- int size = 0, offset = 0;
-
- assert(buf);
- assert(len > 0);
- assert(data);
-
- switch (opt) {
- case IPSET_OPT_FAMILY:
- size = ipset_print_family(buf, len, data, opt, env);
- break;
- case IPSET_OPT_TYPE:
- size = ipset_print_type(buf, len, data, opt, env);
- break;
- case IPSET_SETNAME:
- size = snprintf(buf, len, "%s", ipset_data_setname(data));
- break;
- case IPSET_OPT_ELEM:
- size = ipset_print_elem(buf, len, data, opt, env);
- break;
- case IPSET_OPT_IP:
- size = ipset_print_ip(buf, len, data, opt, env);
- break;
- case IPSET_OPT_PORT:
- size = ipset_print_port(buf, len, data, opt, env);
- break;
- case IPSET_OPT_IFACE:
- size = ipset_print_iface(buf, len, data, opt, env);
- break;
- case IPSET_OPT_GC:
- case IPSET_OPT_HASHSIZE:
- case IPSET_OPT_MAXELEM:
- case IPSET_OPT_NETMASK:
- case IPSET_OPT_PROBES:
- case IPSET_OPT_RESIZE:
- case IPSET_OPT_TIMEOUT:
- case IPSET_OPT_REFERENCES:
- case IPSET_OPT_ELEMENTS:
- case IPSET_OPT_SIZE:
- size = ipset_print_number(buf, len, data, opt, env);
- break;
- default:
- return -1;
- }
- SNPRINTF_FAILURE(size, len, offset);
-
- return offset;
-}
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <assert.h> /* assert */
-#include <errno.h> /* errno */
-#include <setjmp.h> /* setjmp, longjmp */
-#include <stdio.h> /* snprintf */
-#include <stdarg.h> /* va_* */
-#include <stdlib.h> /* free */
-#include <string.h> /* str* */
-#include <unistd.h> /* getpagesize */
-#include <net/ethernet.h> /* ETH_ALEN */
-#include <net/if.h> /* IFNAMSIZ */
-
-#include <libipset/debug.h> /* D() */
-#include <libipset/data.h> /* IPSET_OPT_* */
-#include <libipset/errcode.h> /* ipset_errcode */
-#include <libipset/print.h> /* ipset_print_* */
-#include <libipset/types.h> /* struct ipset_type */
-#include <libipset/transport.h> /* transport */
-#include <libipset/mnl.h> /* default backend */
-#include <libipset/utils.h> /* STREQ */
-#include <libipset/ui.h> /* IPSET_ENV_* */
-#include <libipset/session.h> /* prototypes */
-
-#include <linux/genetlink.h>
-
-#define IPSET_NEST_MAX 4
-
-/* The session structure */
-struct ipset_session {
- const struct ipset_transport *transport;/* Transport protocol */
- struct ipset_handle *handle; /* Transport handler */
- struct ipset_data *data; /* Input/output data */
- /* Command state */
- enum ipset_cmd cmd; /* Current command */
- uint32_t lineno; /* Current lineno in restore mode */
- uint32_t printed_set; /* Printed sets so far */
- char saved_setname[IPSET_MAXNAMELEN]; /* Saved setname */
- const struct ipset_type *saved_type; /* Saved type */
- struct nlattr *nested[IPSET_NEST_MAX]; /* Pointer to nest levels */
- uint8_t nestid; /* Current nest level */
- bool version_checked; /* Version checked */
- /* Output buffer */
- char outbuf[IPSET_OUTBUFLEN]; /* Output buffer */
- enum ipset_output_mode mode; /* Output mode */
- ipset_outfn outfn; /* Output function */
- /* Error/warning reporting */
- char report[IPSET_ERRORBUFLEN]; /* Error/report buffer */
- char *errmsg;
- char *warnmsg;
- uint8_t envopts; /* Session env opts */
- /* Kernel message buffer */
- size_t bufsize;
- void *buffer;
-};
-
-/*
- * Glue functions
- */
-
-/**
- * ipset_session_data - return pointer to the data
- * @session: session structure
- *
- * Returns the pointer to the data structure of the session.
- */
-struct ipset_data *
-ipset_session_data(const struct ipset_session *session)
-{
- assert(session);
- return session->data;
-}
-
-/**
- * ipset_session_handle - return pointer to the handle
- * @session: session structure
- *
- * Returns the pointer to the transport handle structure of the session.
- */
-struct ipset_handle *
-ipset_session_handle(const struct ipset_session *session)
-{
- assert(session);
- return session->handle;
-}
-
-/**
- * ipset_saved_type - return pointer to the saved type
- * @session: session structure
- *
- * Returns the pointer to the saved type from the last ipset_cmd
- * It is required to decode type-specific error codes in restore mode.
- */
-const struct ipset_type *
-ipset_saved_type(const struct ipset_session *session)
-{
- assert(session);
- return session->saved_type;
-}
-
-/**
- * ipset_session_lineno - set session lineno
- * @session: session structure
- *
- * Set session lineno to report parser errors correctly.
- */
-void
-ipset_session_lineno(struct ipset_session *session, uint32_t lineno)
-{
- assert(session);
- session->lineno = lineno;
-}
-
-/*
- * Environment options
- */
-
-/**
- * ipset_envopt_parse - parse/set environment option
- * @session: session structure
- * @opt: environment option
- * @arg: option argument (unused)
- *
- * Parse and set an environment option.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_envopt_parse(struct ipset_session *session, int opt,
- const char *arg UNUSED)
-{
- assert(session);
-
- switch (opt) {
- case IPSET_ENV_SORTED:
- case IPSET_ENV_QUIET:
- case IPSET_ENV_RESOLVE:
- case IPSET_ENV_EXIST:
- case IPSET_ENV_LIST_SETNAME:
- case IPSET_ENV_LIST_HEADER:
- session->envopts |= opt;
- return 0;
- default:
- break;
- }
- return -1;
-}
-
-/**
- * ipset_envopt_test - test environment option
- * @session: session structure
- * @opt: environment option
- *
- * Test whether the environment option is set in the session.
- *
- * Returns true or false.
- */
-bool
-ipset_envopt_test(struct ipset_session *session, enum ipset_envopt opt)
-{
- assert(session);
- return session->envopts & opt;
-}
-
-/**
- * ipset_session_output - set the session output mode
- * @session: session structure
- * @mode: output mode
- *
- * Set the output mode for the session.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_session_output(struct ipset_session *session,
- enum ipset_output_mode mode)
-{
- assert(session);
- session->mode = mode;
- return 0;
-}
-
-/*
- * Error and warning reporting
- */
-
-/**
- * ipset_session_report - fill the report buffer
- * @session: session structure
- * @type: report type
- * @fmt: message format
- *
- * Fill the report buffer with an error or warning message.
- * Depending on the report type, set the error or warning
- * message pointer.
- *
- * Returns -1.
- */
-int __attribute__((format(printf, 3, 4)))
-ipset_session_report(struct ipset_session *session,
- enum ipset_err_type type,
- const char *fmt, ...)
-{
- int len, offset = 0;
- va_list args;
-
- assert(session);
- assert(fmt);
-
- if (session->lineno != 0 && type == IPSET_ERROR) {
- sprintf(session->report, "Error in line %u: ",
- session->lineno);
- }
- offset = strlen(session->report);
-
- va_start(args, fmt);
- len = vsnprintf(session->report + offset,
- IPSET_ERRORBUFLEN - 1 - offset,
- fmt, args);
- va_end(args);
-
- if (len >= IPSET_ERRORBUFLEN - 1 - offset)
- session->report[IPSET_ERRORBUFLEN - 1] = '\0';
- if (strlen(session->report) < IPSET_ERRORBUFLEN - 1)
- strcat(session->report, "\n");
-
- if (type == IPSET_ERROR) {
- session->errmsg = session->report;
- session->warnmsg = NULL;
- } else {
- session->errmsg = NULL;
- session->warnmsg = session->report;
- }
- return -1;
-}
-
-/**
- * ipset_session_reset - reset the report buffer
- * @session: session structure
- *
- * Reset the report buffer, the error and warning pointers.
- */
-void
-ipset_session_report_reset(struct ipset_session *session)
-{
- assert(session);
- session->report[0] = '\0';
- session->errmsg = session->warnmsg = NULL;
-}
-
-/**
- * ipset_session_error - return the report buffer as error
- * @session: session structure
- *
- * Return the pointer to the report buffer as an error report.
- * If there is no error message in the buffer, NULL returned.
- */
-const char *
-ipset_session_error(const struct ipset_session *session)
-{
- assert(session);
-
- return session->errmsg;
-}
-
-/**
- * ipset_session_warning - return the report buffer as warning
- * @session: session structure
- *
- * Return the pointer to the report buffer as a warning report.
- * If there is no warning message in the buffer, NULL returned.
- */
-const char *
-ipset_session_warning(const struct ipset_session *session)
-{
- assert(session);
-
- return session->warnmsg;
-}
-
-/*
- * Receive data from the kernel
- */
-
-struct ipset_attr_policy {
- uint16_t type;
- uint16_t len;
- enum ipset_opt opt;
-};
-
-/* Attribute policies and mapping to options */
-static const struct ipset_attr_policy cmd_attrs[] = {
- [IPSET_ATTR_PROTOCOL] = {
- .type = MNL_TYPE_U8,
- },
- [IPSET_ATTR_SETNAME] = {
- .type = MNL_TYPE_NUL_STRING,
- .opt = IPSET_SETNAME,
- .len = IPSET_MAXNAMELEN,
- },
- [IPSET_ATTR_TYPENAME] = {
- .type = MNL_TYPE_NUL_STRING,
- .opt = IPSET_OPT_TYPENAME,
- .len = IPSET_MAXNAMELEN,
- },
- /* IPSET_ATTR_SETNAME2 is an alias for IPSET_ATTR_TYPENAME */
- [IPSET_ATTR_REVISION] = {
- .type = MNL_TYPE_U8,
- .opt = IPSET_OPT_REVISION,
- },
- [IPSET_ATTR_FAMILY] = {
- .type = MNL_TYPE_U8,
- .opt = IPSET_OPT_FAMILY,
- },
- [IPSET_ATTR_FLAGS] = {
- .type = MNL_TYPE_U32,
- .opt = IPSET_OPT_FLAGS,
- },
- [IPSET_ATTR_DATA] = {
- .type = MNL_TYPE_NESTED,
- },
- [IPSET_ATTR_ADT] = {
- .type = MNL_TYPE_NESTED,
- },
- [IPSET_ATTR_REVISION_MIN] = {
- .type = MNL_TYPE_U8,
- .opt = IPSET_OPT_REVISION_MIN,
- },
- /* IPSET_ATTR_PROTOCOL_MIN is an alias for IPSET_ATTR_REVISION_MIN */
- [IPSET_ATTR_LINENO] = {
- .type = MNL_TYPE_U32,
- .opt = IPSET_OPT_LINENO,
- },
-};
-
-static const struct ipset_attr_policy create_attrs[] = {
- [IPSET_ATTR_IP] = {
- .type = MNL_TYPE_NESTED,
- .opt = IPSET_OPT_IP,
- },
- [IPSET_ATTR_IP_TO] = {
- .type = MNL_TYPE_NESTED,
- .opt = IPSET_OPT_IP_TO,
- },
- [IPSET_ATTR_CIDR] = {
- .type = MNL_TYPE_U8,
- .opt = IPSET_OPT_CIDR,
- },
- [IPSET_ATTR_PORT] = {
- .type = MNL_TYPE_U16,
- .opt = IPSET_OPT_PORT,
- },
- [IPSET_ATTR_PORT_TO] = {
- .type = MNL_TYPE_U16,
- .opt = IPSET_OPT_PORT_TO,
- },
- [IPSET_ATTR_TIMEOUT] = {
- .type = MNL_TYPE_U32,
- .opt = IPSET_OPT_TIMEOUT,
- },
- [IPSET_ATTR_PROTO] = {
- .type = MNL_TYPE_U8,
- .opt = IPSET_OPT_PROTO,
- },
- [IPSET_ATTR_CADT_FLAGS] = {
- .type = MNL_TYPE_U32,
- .opt = IPSET_OPT_CADT_FLAGS,
- },
- [IPSET_ATTR_GC] = {
- .type = MNL_TYPE_U32,
- .opt = IPSET_OPT_GC,
- },
- [IPSET_ATTR_HASHSIZE] = {
- .type = MNL_TYPE_U32,
- .opt = IPSET_OPT_HASHSIZE,
- },
- [IPSET_ATTR_MAXELEM] = {
- .type = MNL_TYPE_U32,
- .opt = IPSET_OPT_MAXELEM,
- },
- [IPSET_ATTR_NETMASK] = {
- .type = MNL_TYPE_U8,
- .opt = IPSET_OPT_NETMASK,
- },
- [IPSET_ATTR_PROBES] = {
- .type = MNL_TYPE_U8,
- .opt = IPSET_OPT_PROBES,
- },
- [IPSET_ATTR_RESIZE] = {
- .type = MNL_TYPE_U8,
- .opt = IPSET_OPT_RESIZE,
- },
- [IPSET_ATTR_SIZE] = {
- .type = MNL_TYPE_U32,
- .opt = IPSET_OPT_SIZE,
- },
- [IPSET_ATTR_ELEMENTS] = {
- .type = MNL_TYPE_U32,
- .opt = IPSET_OPT_ELEMENTS,
- },
- [IPSET_ATTR_REFERENCES] = {
- .type = MNL_TYPE_U32,
- .opt = IPSET_OPT_REFERENCES,
- },
- [IPSET_ATTR_MEMSIZE] = {
- .type = MNL_TYPE_U32,
- .opt = IPSET_OPT_MEMSIZE,
- },
-};
-
-static const struct ipset_attr_policy adt_attrs[] = {
- [IPSET_ATTR_IP] = {
- .type = MNL_TYPE_NESTED,
- .opt = IPSET_OPT_IP,
- },
- [IPSET_ATTR_IP_TO] = {
- .type = MNL_TYPE_NESTED,
- .opt = IPSET_OPT_IP_TO,
- },
- [IPSET_ATTR_CIDR] = {
- .type = MNL_TYPE_U8,
- .opt = IPSET_OPT_CIDR,
- },
- [IPSET_ATTR_PORT] = {
- .type = MNL_TYPE_U16,
- .opt = IPSET_OPT_PORT,
- },
- [IPSET_ATTR_PORT_TO] = {
- .type = MNL_TYPE_U16,
- .opt = IPSET_OPT_PORT_TO,
- },
- [IPSET_ATTR_PROTO] = {
- .type = MNL_TYPE_U8,
- .opt = IPSET_OPT_PROTO,
- },
- [IPSET_ATTR_TIMEOUT] = {
- .type = MNL_TYPE_U32,
- .opt = IPSET_OPT_TIMEOUT,
- },
- [IPSET_ATTR_CADT_FLAGS] = {
- .type = MNL_TYPE_U32,
- .opt = IPSET_OPT_CADT_FLAGS,
- },
- [IPSET_ATTR_LINENO] = {
- .type = MNL_TYPE_U32,
- .opt = IPSET_OPT_LINENO,
- },
- [IPSET_ATTR_ETHER] = {
- .type = MNL_TYPE_BINARY,
- .opt = IPSET_OPT_ETHER,
- .len = ETH_ALEN,
- },
- [IPSET_ATTR_NAME] = {
- .type = MNL_TYPE_NUL_STRING,
- .opt = IPSET_OPT_NAME,
- .len = IPSET_MAXNAMELEN,
- },
- [IPSET_ATTR_NAMEREF] = {
- .type = MNL_TYPE_NUL_STRING,
- .opt = IPSET_OPT_NAMEREF,
- .len = IPSET_MAXNAMELEN,
- },
- [IPSET_ATTR_IP2] = {
- .type = MNL_TYPE_NESTED,
- .opt = IPSET_OPT_IP2,
- },
- [IPSET_ATTR_CIDR2] = {
- .type = MNL_TYPE_U8,
- .opt = IPSET_OPT_CIDR2,
- },
- [IPSET_ATTR_IP2_TO] = {
- .type = MNL_TYPE_NESTED,
- .opt = IPSET_OPT_IP2_TO,
- },
- [IPSET_ATTR_IFACE] = {
- .type = MNL_TYPE_NUL_STRING,
- .opt = IPSET_OPT_IFACE,
- .len = IFNAMSIZ,
- },
-};
-
-static const struct ipset_attr_policy ipaddr_attrs[] = {
- [IPSET_ATTR_IPADDR_IPV4] = {
- .type = MNL_TYPE_U32,
- },
- [IPSET_ATTR_IPADDR_IPV6] = {
- .type = MNL_TYPE_BINARY,
- .len = sizeof(union nf_inet_addr),
- },
-};
-
-#ifdef IPSET_DEBUG
-static int debug = 1;
-#endif
-
-static int
-generic_data_attr_cb(const struct nlattr *attr, void *data,
- int attr_max, const struct ipset_attr_policy *policy)
-{
- const struct nlattr **tb = data;
- int type = mnl_attr_get_type(attr);
-
- IF_D(debug, "attr type: %u, len %u", type, attr->nla_len);
- if (mnl_attr_type_valid(attr, attr_max) < 0) {
- IF_D(debug, "attr type: %u INVALID", type);
- return MNL_CB_ERROR;
- }
- if (mnl_attr_validate(attr, policy[type].type) < 0) {
- IF_D(debug, "attr type: %u POLICY, attrlen %u", type,
- mnl_attr_get_payload_len(attr));
- return MNL_CB_ERROR;
- }
- if (policy[type].type == MNL_TYPE_NUL_STRING &&
- mnl_attr_get_payload_len(attr) > IPSET_MAXNAMELEN)
- return MNL_CB_ERROR;
- tb[type] = attr;
- return MNL_CB_OK;
-}
-
-static int
-create_attr_cb(const struct nlattr *attr, void *data)
-{
- return generic_data_attr_cb(attr, data,
- IPSET_ATTR_CREATE_MAX, create_attrs);
-}
-
-static int
-adt_attr_cb(const struct nlattr *attr, void *data)
-{
- return generic_data_attr_cb(attr, data,
- IPSET_ATTR_ADT_MAX, adt_attrs);
-}
-
-static int
-ipaddr_attr_cb(const struct nlattr *attr, void *data)
-{
- return generic_data_attr_cb(attr, data,
- IPSET_ATTR_IPADDR_MAX, ipaddr_attrs);
-}
-
-#define FAILURE(format, args...) \
- { ipset_err(session, format , ## args); return MNL_CB_ERROR; }
-
-static int
-attr2data(struct ipset_session *session, struct nlattr *nla[],
- int type, const struct ipset_attr_policy attrs[])
-{
- struct ipset_data *data = session->data;
- const struct ipset_attr_policy *attr;
- const void *d;
- int ret;
-
- attr = &attrs[type];
- d = mnl_attr_get_payload(nla[type]);
-
- if (attr->type == MNL_TYPE_NESTED && attr->opt) {
- /* IP addresses */
- struct nlattr *ipattr[IPSET_ATTR_IPADDR_MAX+1] = {};
- uint8_t family = ipset_data_family(data);
- int atype;
- D("attr type %u", type);
- if (mnl_attr_parse_nested(nla[type],
- ipaddr_attr_cb, ipattr) < 0)
- FAILURE("Broken kernel message, cannot validate "
- "IP address attribute!");
-
- /* Validate by hand */
- switch (family) {
- case NFPROTO_IPV4:
- atype = IPSET_ATTR_IPADDR_IPV4;
- if (!ipattr[atype])
- FAILURE("Broken kernel message: IPv4 address "
- "expected but not received!");
- if (ipattr[atype]->nla_len < sizeof(uint32_t))
- FAILURE("Broken kernel message: "
- "cannot validate IPv4 "
- "address attribute!");
- break;
- case NFPROTO_IPV6:
- atype = IPSET_ATTR_IPADDR_IPV6;
- if (!ipattr[atype])
- FAILURE("Broken kernel message: IPv6 address "
- "expected but not received!");
- if (ipattr[atype]->nla_len < sizeof(struct in6_addr))
- FAILURE("Broken kernel message: "
- "cannot validate IPv6 "
- "address attribute!");
- break;
- default:
- FAILURE("Broken kernel message: "
- "IP address attribute but "
- "family is unspecified!");
- }
- d = mnl_attr_get_payload(ipattr[atype]);
- } else if (nla[type]->nla_type & NLA_F_NET_BYTEORDER) {
- switch (attr->type) {
- case MNL_TYPE_U32: {
- uint32_t value;
-
- value = ntohl(*(const uint32_t *)d);
-
- d = &value;
- break;
- }
- case MNL_TYPE_U16: {
- uint16_t value;
-
- value = ntohs(*(const uint16_t *)d);
-
- d = &value;
- break;
- }
- default:
- break;
- }
- }
-#ifdef IPSET_DEBUG
- if (type == IPSET_ATTR_TYPENAME)
- D("nla typename %s", (const char *) d);
-#endif
- ret = ipset_data_set(data, attr->opt, d);
-#ifdef IPSET_DEBUG
- if (type == IPSET_ATTR_TYPENAME)
- D("nla typename %s",
- (const char *) ipset_data_get(data, IPSET_OPT_TYPENAME));
-#endif
- return ret;
-}
-
-#define ATTR2DATA(session, nla, type, attrs) \
- if (attr2data(session, nla, type, attrs) < 0) \
- return MNL_CB_ERROR
-
-static const char cmd2name[][9] = {
- [IPSET_CMD_NONE] = "NONE",
- [IPSET_CMD_CREATE] = "CREATE",
- [IPSET_CMD_DESTROY] = "DESTROY",
- [IPSET_CMD_FLUSH] = "FLUSH",
- [IPSET_CMD_RENAME] = "RENAME",
- [IPSET_CMD_SWAP] = "SWAP",
- [IPSET_CMD_LIST] = "LIST",
- [IPSET_CMD_SAVE] = "SAVE",
- [IPSET_CMD_ADD] = "ADD",
- [IPSET_CMD_DEL] = "DEL",
- [IPSET_CMD_TEST] = "TEST",
- [IPSET_CMD_HEADER] = "HEADER",
- [IPSET_CMD_TYPE] = "TYPE",
- [IPSET_CMD_PROTOCOL] = "PROTOCOL",
-};
-
-static inline int
-call_outfn(struct ipset_session *session)
-{
- int ret = session->outfn("%s", session->outbuf);
-
- session->outbuf[0] = '\0';
-
- return ret < 0 ? ret : 0;
-}
-
-/* Handle printing failures */
-static jmp_buf printf_failure;
-
-static int __attribute__((format(printf, 2, 3)))
-safe_snprintf(struct ipset_session *session, const char *fmt, ...)
-{
- va_list args;
- int len, ret, loop = 0;
-
-retry:
- len = strlen(session->outbuf);
- D("len: %u, retry %u", len, loop);
- va_start(args, fmt);
- ret = vsnprintf(session->outbuf + len, IPSET_OUTBUFLEN - len,
- fmt, args);
- va_end(args);
-
- if (ret < 0) {
- ipset_err(session,
- "Internal error at printing to output buffer");
- longjmp(printf_failure, 1);
- }
-
- if (ret >= IPSET_OUTBUFLEN - len) {
- /* Buffer was too small, push it out and retry */
- D("print buffer and try again: %u", len);
- if (loop++) {
- ipset_err(session,
- "Internal error at printing, loop detected!");
- longjmp(printf_failure, 1);
- }
-
- session->outbuf[len] = '\0';
- if (!call_outfn(session))
- goto retry;
- }
- return ret;
-}
-
-static int
-safe_dprintf(struct ipset_session *session, ipset_printfn fn,
- enum ipset_opt opt)
-{
- int len, ret, loop = 0;
-
-retry:
- len = strlen(session->outbuf);
- D("len: %u, retry %u", len, loop);
- ret = fn(session->outbuf + len, IPSET_OUTBUFLEN - len,
- session->data, opt, session->envopts);
-
- if (ret < 0) {
- ipset_err(session,
- "Internal error at printing to output buffer");
- longjmp(printf_failure, 1);
- }
-
- if (ret >= IPSET_OUTBUFLEN - len) {
- /* Buffer was too small, push it out and retry */
- D("print buffer and try again: %u", len);
- if (loop++) {
- ipset_err(session,
- "Internal error at printing, loop detected!");
- longjmp(printf_failure, 1);
- }
-
- session->outbuf[len] = '\0';
- if (!call_outfn(session))
- goto retry;
- }
- return ret;
-}
-
-static int
-list_adt(struct ipset_session *session, struct nlattr *nla[])
-{
- const struct ipset_data *data = session->data;
- const struct ipset_type *type;
- const struct ipset_arg *arg;
- uint8_t family;
- int i, found = 0;
-
- D("enter");
- /* Check and load type, family */
- if (!ipset_data_test(data, IPSET_OPT_TYPE))
- type = ipset_type_get(session, IPSET_CMD_ADD);
- else
- type = ipset_data_get(data, IPSET_OPT_TYPE);
-
- if (type == NULL)
- return MNL_CB_ERROR;
- family = ipset_data_family(data);
-
- for (i = IPSET_ATTR_UNSPEC + 1; i <= IPSET_ATTR_ADT_MAX; i++)
- if (nla[i]) {
- found++;
- ATTR2DATA(session, nla, i, adt_attrs);
- }
- D("attr found %u", found);
- if (!found)
- return MNL_CB_OK;
-
- switch (session->mode) {
- case IPSET_LIST_SAVE:
- safe_snprintf(session, "add %s ", ipset_data_setname(data));
- break;
- case IPSET_LIST_XML:
- safe_snprintf(session, " <member>");
- break;
- case IPSET_LIST_PLAIN:
- default:
- break;
- }
-
- safe_dprintf(session, ipset_print_elem, IPSET_OPT_ELEM);
-
- for (arg = type->args[IPSET_ADD]; arg != NULL && arg->print; arg++) {
- if (!ipset_data_test(data, arg->opt))
- continue;
- switch (session->mode) {
- case IPSET_LIST_SAVE:
- case IPSET_LIST_PLAIN:
- safe_snprintf(session, " %s ", arg->name[0]);
- if (arg->has_arg == IPSET_NO_ARG)
- break;
- safe_dprintf(session, arg->print, arg->opt);
- break;
- case IPSET_LIST_XML:
- if (arg->has_arg == IPSET_NO_ARG) {
- safe_snprintf(session,
- " <%s/>\n",
- arg->name[0]);
- break;
- }
- safe_snprintf(session, " <%s>",
- arg->name[0]);
- safe_dprintf(session, arg->print, arg->opt);
- safe_snprintf(session, "</%s>\n",
- arg->name[0]);
- break;
- default:
- break;
- }
- }
-
- if (session->mode == IPSET_LIST_XML)
- safe_snprintf(session, "</member>\n");
- else
- safe_snprintf(session, "\n");
-
- return MNL_CB_OK;
-}
-
-#define FAMILY_TO_STR(f) \
- ((f) == NFPROTO_IPV4 ? "inet" : \
- (f) == NFPROTO_IPV6 ? "inet6" : "any")
-
-static int
-list_create(struct ipset_session *session, struct nlattr *nla[])
-{
- const struct ipset_data *data = session->data;
- const struct ipset_type *type;
- const struct ipset_arg *arg;
- uint8_t family;
- int i;
-
- for (i = IPSET_ATTR_UNSPEC + 1; i <= IPSET_ATTR_CREATE_MAX; i++)
- if (nla[i]) {
- D("add attr %u, opt %u", i, create_attrs[i].opt);
- ATTR2DATA(session, nla, i, create_attrs);
- }
-
- type = ipset_type_check(session);
- if (type == NULL)
- return MNL_CB_ERROR;
- family = ipset_data_family(data);
-
- switch (session->mode) {
- case IPSET_LIST_SAVE:
- safe_snprintf(session, "create %s %s ",
- ipset_data_setname(data),
- type->name);
- break;
- case IPSET_LIST_PLAIN:
- safe_snprintf(session, "%sName: %s\n"
- "Type: %s\nHeader: ",
- session->printed_set ? "\n" : "",
- ipset_data_setname(data),
- type->name);
- break;
- case IPSET_LIST_XML:
- safe_snprintf(session,
- "<ipset name=\"%s\">\n"
- " <type>%s</type>\n"
- " <header>\n",
- ipset_data_setname(data),
- type->name);
- break;
- default:
- break;
- }
-
- for (arg = type->args[IPSET_CREATE]; arg != NULL && arg->opt; arg++) {
- if (!arg->print ||
- !ipset_data_test(data, arg->opt) ||
- (arg->opt == IPSET_OPT_FAMILY &&
- family == type->family))
- continue;
- switch (session->mode) {
- case IPSET_LIST_SAVE:
- case IPSET_LIST_PLAIN:
- safe_snprintf(session, "%s ", arg->name[0]);
- if (arg->has_arg == IPSET_NO_ARG)
- break;
- safe_dprintf(session, arg->print, arg->opt);
- safe_snprintf(session, " ");
- break;
- case IPSET_LIST_XML:
- if (arg->has_arg == IPSET_NO_ARG) {
- safe_snprintf(session,
- " <%s/>\n",
- arg->name[0]);
- break;
- }
- safe_snprintf(session, " <%s>",
- arg->name[0]);
- safe_dprintf(session, arg->print, arg->opt);
- safe_snprintf(session, "</%s>\n",
- arg->name[0]);
- break;
- default:
- break;
- }
- }
- switch (session->mode) {
- case IPSET_LIST_SAVE:
- safe_snprintf(session, "\n");
- break;
- case IPSET_LIST_PLAIN:
- safe_snprintf(session, "\nSize in memory: ");
- safe_dprintf(session, ipset_print_number, IPSET_OPT_MEMSIZE);
- safe_snprintf(session, "\nReferences: ");
- safe_dprintf(session, ipset_print_number, IPSET_OPT_REFERENCES);
- safe_snprintf(session,
- session->envopts & IPSET_ENV_LIST_HEADER ?
- "\n" : "\nMembers:\n");
- break;
- case IPSET_LIST_XML:
- safe_snprintf(session, " <memsize>");
- safe_dprintf(session, ipset_print_number, IPSET_OPT_MEMSIZE);
- safe_snprintf(session, "</memsize>\n <references>");
- safe_dprintf(session, ipset_print_number, IPSET_OPT_REFERENCES);
- safe_snprintf(session,
- session->envopts & IPSET_ENV_LIST_HEADER ?
- "</references>\n </header>\n" :
- "</references>\n </header>\n <members>\n");
- break;
- default:
- break;
- }
- session->printed_set++;
-
- return MNL_CB_OK;
-}
-
-static int
-print_set_done(struct ipset_session *session)
-{
- D("called for %s", session->saved_setname[0] == '\0'
- ? "NONE" : session->saved_setname);
- switch (session->mode) {
- case IPSET_LIST_XML:
- if (session->envopts & IPSET_ENV_LIST_SETNAME)
- break;
- if (session->envopts & IPSET_ENV_LIST_HEADER) {
- if (session->saved_setname[0] != '\0')
- safe_snprintf(session, "</ipset>\n");
- break;
- }
- if (session->saved_setname[0] != '\0')
- safe_snprintf(session, " </members>\n</ipset>\n");
- break;
- default:
- break;
- }
- return call_outfn(session) ? MNL_CB_ERROR : MNL_CB_STOP;
-}
-
-static int
-callback_list(struct ipset_session *session, struct nlattr *nla[],
- enum ipset_cmd cmd)
-{
- struct ipset_data *data = session->data;
-
- if (setjmp(printf_failure)) {
- session->saved_setname[0] = '\0';
- session->printed_set = 0;
- return MNL_CB_ERROR;
- }
-
- if (!nla[IPSET_ATTR_SETNAME])
- FAILURE("Broken %s kernel message: missing setname!",
- cmd2name[cmd]);
-
- ATTR2DATA(session, nla, IPSET_ATTR_SETNAME, cmd_attrs);
- D("setname %s", ipset_data_setname(data));
- if (session->envopts & IPSET_ENV_LIST_SETNAME &&
- session->mode != IPSET_LIST_SAVE) {
- if (session->mode == IPSET_LIST_XML)
- safe_snprintf(session, "<ipset name=\"%s\"/>\n",
- ipset_data_setname(data));
- else
- safe_snprintf(session, "%s\n",
- ipset_data_setname(data));
- return call_outfn(session) ? MNL_CB_ERROR : MNL_CB_OK;
- }
-
- if (STREQ(ipset_data_setname(data), session->saved_setname)) {
- /* Header part already seen */
- if (ipset_data_test(data, IPSET_OPT_TYPE) &&
- nla[IPSET_ATTR_DATA] != NULL)
- FAILURE("Broken %s kernel message: "
- "extra DATA received!", cmd2name[cmd]);
- } else {
- if (nla[IPSET_ATTR_DATA] == NULL)
- FAILURE("Broken %s kernel message: "
- "missing DATA part!", cmd2name[cmd]);
-
- /* Close previous set printing */
- if (session->saved_setname[0] != '\0')
- print_set_done(session);
- }
-
- if (nla[IPSET_ATTR_DATA] != NULL) {
- struct nlattr *cattr[IPSET_ATTR_CREATE_MAX+1] = {};
-
- if (!(nla[IPSET_ATTR_TYPENAME] &&
- nla[IPSET_ATTR_FAMILY] &&
- nla[IPSET_ATTR_REVISION]))
- FAILURE("Broken %s kernel message: missing %s!",
- cmd2name[cmd],
- !nla[IPSET_ATTR_TYPENAME] ? "typename" :
- !nla[IPSET_ATTR_FAMILY] ? "family" :
- "revision");
-
- /* Reset CREATE specific flags */
- ipset_data_flags_unset(data, IPSET_CREATE_FLAGS);
- D("nla typename %s",
- (char *) mnl_attr_get_payload(nla[IPSET_ATTR_TYPENAME]));
- D("nla typename %s",
- (char *) mnl_attr_get_payload(nla[IPSET_ATTR_TYPENAME]));
- ATTR2DATA(session, nla, IPSET_ATTR_FAMILY, cmd_attrs);
- ATTR2DATA(session, nla, IPSET_ATTR_TYPENAME, cmd_attrs);
- ATTR2DATA(session, nla, IPSET_ATTR_REVISION, cmd_attrs);
- D("head: family %u, typename %s",
- ipset_data_family(data),
- (const char *) ipset_data_get(data, IPSET_OPT_TYPENAME));
- if (mnl_attr_parse_nested(nla[IPSET_ATTR_DATA],
- create_attr_cb, cattr) < 0)
- FAILURE("Broken %s kernel message: "
- "cannot validate DATA attributes!",
- cmd2name[cmd]);
- if (list_create(session, cattr) != MNL_CB_OK)
- return MNL_CB_ERROR;
- strcpy(session->saved_setname, ipset_data_setname(data));
- }
-
- if (nla[IPSET_ATTR_ADT] != NULL) {
- struct nlattr *tb, *adt[IPSET_ATTR_ADT_MAX+1];
-
- mnl_attr_for_each_nested(tb, nla[IPSET_ATTR_ADT]) {
- D("ADT attributes for %s", ipset_data_setname(data));
- memset(adt, 0, sizeof(adt));
- /* Reset ADT specific flags */
- ipset_data_flags_unset(data, IPSET_ADT_FLAGS);
- if (mnl_attr_parse_nested(tb, adt_attr_cb, adt) < 0)
- FAILURE("Broken %s kernel message: "
- "cannot validate ADT attributes!",
- cmd2name[cmd]);
- if (list_adt(session, adt) != MNL_CB_OK)
- return MNL_CB_ERROR;
- }
- }
- return call_outfn(session) ? MNL_CB_ERROR : MNL_CB_OK;
-}
-
-#ifndef IPSET_PROTOCOL_MIN
-#define IPSET_PROTOCOL_MIN IPSET_PROTOCOL
-#endif
-
-#ifndef IPSET_PROTOCOL_MAX
-#define IPSET_PROTOCOL_MAX IPSET_PROTOCOL
-#endif
-
-static int
-callback_version(struct ipset_session *session, struct nlattr *nla[])
-{
- uint8_t min, max;
-
- min = max = mnl_attr_get_u8(nla[IPSET_ATTR_PROTOCOL]);
-
- if (nla[IPSET_ATTR_PROTOCOL_MIN]) {
- min = mnl_attr_get_u8(nla[IPSET_ATTR_PROTOCOL_MIN]);
- D("min: %u", min);
- }
-
- if (min > IPSET_PROTOCOL_MAX || max < IPSET_PROTOCOL_MIN)
- FAILURE("Cannot communicate with kernel: "
- "Kernel support protocol versions %u-%u "
- "while userspace supports protocol versions %u-%u",
- min, max, IPSET_PROTOCOL_MIN, IPSET_PROTOCOL_MAX);
-
- if (!(session->envopts & IPSET_ENV_QUIET) &&
- max != IPSET_PROTOCOL_MAX)
- ipset_warn(session,
- "Kernel support protocol versions %u-%u "
- "while userspace supports protocol versions %u-%u",
- min, max, IPSET_PROTOCOL_MIN, IPSET_PROTOCOL_MAX);
-
- session->version_checked = true;
-
- return MNL_CB_STOP;
-}
-
-static int
-callback_header(struct ipset_session *session, struct nlattr *nla[])
-{
- const char *setname;
- const struct ipset_data *data = session->data;
-
- if (!nla[IPSET_ATTR_SETNAME])
- FAILURE("Broken HEADER kernel message: missing setname!");
-
- setname = mnl_attr_get_str(nla[IPSET_ATTR_SETNAME]);
- if (!STREQ(setname, ipset_data_setname(data)))
- FAILURE("Broken HEADER kernel message: sent setname `%s' "
- "does not match with received one `%s'!",
- ipset_data_setname(data), setname);
-
- if (!(nla[IPSET_ATTR_TYPENAME] &&
- nla[IPSET_ATTR_REVISION] &&
- nla[IPSET_ATTR_FAMILY]))
- FAILURE("Broken HEADER kernel message: "
- "missing attribute '%s'!",
- !nla[IPSET_ATTR_TYPENAME] ? "typename" :
- !nla[IPSET_ATTR_REVISION] ? "revision" :
- "family");
-
- ATTR2DATA(session, nla, IPSET_ATTR_TYPENAME, cmd_attrs);
- ATTR2DATA(session, nla, IPSET_ATTR_REVISION, cmd_attrs);
- ATTR2DATA(session, nla, IPSET_ATTR_FAMILY, cmd_attrs);
- D("got family: %u", ipset_data_family(session->data));
-
- return MNL_CB_STOP;
-}
-
-static int
-callback_type(struct ipset_session *session, struct nlattr *nla[])
-{
- const struct ipset_data *data = session->data;
- const char *typename, *orig;
-
- if (!(nla[IPSET_ATTR_TYPENAME] &&
- nla[IPSET_ATTR_REVISION] &&
- nla[IPSET_ATTR_FAMILY]))
- FAILURE("Broken TYPE kernel message: "
- "missing attribute '%s'!",
- !nla[IPSET_ATTR_TYPENAME] ? "typename" :
- !nla[IPSET_ATTR_REVISION] ? "revision" :
- "family");
-
- typename = mnl_attr_get_str(nla[IPSET_ATTR_TYPENAME]);
- orig = ipset_data_get(data, IPSET_OPT_TYPENAME);
- if (!STREQ(typename, orig))
- FAILURE("Broken TYPE kernel message: sent typename `%s' "
- "does not match with received one `%s'!",
- orig, typename);
-
- ATTR2DATA(session, nla, IPSET_ATTR_TYPENAME, cmd_attrs);
- ATTR2DATA(session, nla, IPSET_ATTR_REVISION, cmd_attrs);
- ATTR2DATA(session, nla, IPSET_ATTR_FAMILY, cmd_attrs);
- if (nla[IPSET_ATTR_REVISION_MIN])
- ATTR2DATA(session, nla, IPSET_ATTR_REVISION_MIN, cmd_attrs);
-
- return MNL_CB_STOP;
-}
-
-static int
-cmd_attr_cb(const struct nlattr *attr, void *data)
-{
- return generic_data_attr_cb(attr, data, IPSET_ATTR_CMD_MAX, cmd_attrs);
-}
-
-#if 0
-static int
-mnl_attr_parse_dbg(const struct nlmsghdr *nlh, int offset,
- mnl_attr_cb_t cb, void *data)
-{
- int ret = MNL_CB_OK;
- struct nlattr *attr = mnl_nlmsg_get_payload_offset(nlh, offset);
- int len = nlh->nlmsg_len - MNL_NLMSG_HDRLEN - MNL_ALIGN(offset);
-
- while (mnl_attr_ok(attr, len)) {
- D("attr: type %u, attrlen %u, len %u",
- mnl_attr_get_type(attr), attr->nla_len, len);
- if (cb && (ret = cb(attr, data)) <= MNL_CB_STOP)
- return ret;
- attr = mnl_attr_next(attr, &len);
- }
- return ret;
-}
-#endif
-
-static int
-callback_data(const struct nlmsghdr *nlh, void *data)
-{
- struct ipset_session *session = data;
- struct nlattr *nla[IPSET_ATTR_CMD_MAX+1] = {};
- uint8_t proto, cmd;
- int ret = MNL_CB_OK, nfmsglen = MNL_ALIGN(sizeof(struct genlmsghdr));
-
- D("called, nlmsg_len %u", nlh->nlmsg_len);
- cmd = ipset_get_nlmsg_type(nlh);
- if (cmd == IPSET_CMD_LIST && session->cmd == IPSET_CMD_SAVE)
- /* Kernel always send IPSET_CMD_LIST */
- cmd = IPSET_CMD_SAVE;
-
- if (cmd != session->cmd)
- FAILURE("Protocol error, we sent command %s "
- "and received %s[%u]",
- cmd2name[session->cmd],
- cmd < IPSET_MSG_MAX ? cmd2name[cmd] : "unknown", cmd);
-
- if (mnl_attr_parse(nlh, nfmsglen, cmd_attr_cb, nla) < MNL_CB_STOP)
- FAILURE("Broken %s kernel message: "
- "cannot validate and parse attributes",
- cmd2name[cmd]);
-
- if (!nla[IPSET_ATTR_PROTOCOL])
- FAILURE("Sad, sad day: kernel message %s "
- "does not carry the protocol version.",
- cmd2name[cmd]);
-
- proto = mnl_attr_get_u8(nla[IPSET_ATTR_PROTOCOL]);
-
- /* Check protocol */
- if (cmd != IPSET_CMD_PROTOCOL && proto != IPSET_PROTOCOL)
- FAILURE("Giving up: kernel protocol version %u "
- "does not match our protocol version %u",
- proto, IPSET_PROTOCOL);
-
- D("Message: %s", cmd2name[cmd]);
- switch (cmd) {
- case IPSET_CMD_LIST:
- case IPSET_CMD_SAVE:
- ret = callback_list(session, nla, cmd);
- D("flag multi: %u", nlh->nlmsg_flags & NLM_F_MULTI);
- if (ret >= MNL_CB_STOP && !(nlh->nlmsg_flags & NLM_F_MULTI))
- ret = print_set_done(session);
- break;
- case IPSET_CMD_PROTOCOL:
- if (!session->version_checked)
- ret = callback_version(session, nla);
- break;
- case IPSET_CMD_HEADER:
- ret = callback_header(session, nla);
- break;
- case IPSET_CMD_TYPE:
- ret = callback_type(session, nla);
- break;
- default:
- FAILURE("Data message received when not expected at %s",
- cmd2name[session->cmd]);
- }
- D("return code: %s", ret == MNL_CB_STOP ? "stop" :
- ret == MNL_CB_OK ? "ok" : "error");
- return ret;
-}
-
-static int
-callback_done(const struct nlmsghdr *nlh UNUSED, void *data)
-{
- struct ipset_session *session = data;
-
- D(" called");
- if (session->cmd == IPSET_CMD_LIST || session->cmd == IPSET_CMD_SAVE)
- return print_set_done(session);
-
- FAILURE("Invalid message received in non LIST or SAVE state.");
-}
-
-static int
-decode_errmsg(struct ipset_session *session, const struct nlmsghdr *nlh)
-{
- const struct nlmsgerr *err = mnl_nlmsg_get_payload(nlh);
- const struct nlmsghdr *msg = &err->msg;
- struct nlattr *nla[IPSET_ATTR_CMD_MAX+1] = {};
- enum ipset_cmd cmd;
- int nfmsglen = MNL_ALIGN(sizeof(struct genlmsghdr));
-
- if (nlh->nlmsg_len < (uint32_t) MNL_ALIGN(sizeof(struct nlmsgerr))
- || nlh->nlmsg_len < MNL_ALIGN(sizeof(struct nlmsgerr))
- + msg->nlmsg_len)
- FAILURE("Broken error report message received.");
-
- cmd = ipset_get_nlmsg_type(msg);
- D("nlsmg_len: %u", msg->nlmsg_len);
- if (cmd != session->cmd)
- FAILURE("Protocol error, we sent command %s "
- "and received error report for %s[%u]",
- cmd2name[session->cmd],
- cmd < IPSET_MSG_MAX ? cmd2name[cmd] : "unknown", cmd);
-
- if (mnl_attr_parse(msg, nfmsglen, cmd_attr_cb, nla) < MNL_CB_STOP)
- FAILURE("Broken %s error report message: "
- "cannot validate attributes",
- cmd2name[cmd]);
-
- if (!nla[IPSET_ATTR_PROTOCOL])
- FAILURE("Broken %s error report message: "
- "missing protocol attribute",
- cmd2name[cmd]);
-
- if (nla[IPSET_ATTR_LINENO]) {
- session->lineno = mnl_attr_get_u32(nla[IPSET_ATTR_LINENO]);
- if (nla[IPSET_ATTR_LINENO]->nla_type & NLA_F_NET_BYTEORDER)
- session->lineno = ntohl(session->lineno);
- }
-
- return ipset_errcode(session, cmd, -err->error);
-}
-
-static int
-callback_error(const struct nlmsghdr *nlh, void *cbdata)
-{
- struct ipset_session *session = cbdata;
- struct ipset_data *data = session->data;
- const struct nlmsgerr *err = mnl_nlmsg_get_payload(nlh);
- int ret = MNL_CB_ERROR;
-
- D(" called, cmd %s", cmd2name[session->cmd]);
- if (nlh->nlmsg_len < mnl_nlmsg_size(sizeof(struct nlmsgerr)))
- FAILURE("Broken error message received.");
-
- if (err->error == 0) {
- /* ACK */
- ret = MNL_CB_STOP;
-
- switch (session->cmd) {
- case IPSET_CMD_CREATE:
- /* Add successfully created set to the cache */
- ipset_cache_add(ipset_data_setname(data),
- ipset_data_get(data, IPSET_OPT_TYPE),
- ipset_data_family(data));
- break;
- case IPSET_CMD_DESTROY:
- /* Delete destroyed sets from the cache */
- ipset_cache_del(ipset_data_setname(data));
- /* Fall through */
- case IPSET_CMD_FLUSH:
- break;
- case IPSET_CMD_RENAME:
- ipset_cache_rename(ipset_data_setname(data),
- ipset_data_get(data,
- IPSET_OPT_SETNAME2));
- break;
- case IPSET_CMD_SWAP:
- ipset_cache_swap(ipset_data_setname(data),
- ipset_data_get(data,
- IPSET_OPT_SETNAME2));
- break;
- case IPSET_CMD_TEST:
- if (!(session->envopts & IPSET_ENV_QUIET)) {
- ipset_print_elem(session->report,
- IPSET_ERRORBUFLEN,
- session->data,
- IPSET_OPT_NONE, 0);
- ipset_warn(session, " is in set %s.",
- ipset_data_setname(data));
- }
- /* Fall through */
- case IPSET_CMD_ADD:
- case IPSET_CMD_DEL:
- break;
- case IPSET_CMD_LIST:
- case IPSET_CMD_SAVE:
- /* No set in kernel */
- print_set_done(session);
- break;
- default:
- FAILURE("ACK message received to command %s[%u], "
- "which is not expected",
- session->cmd < IPSET_MSG_MAX
- ? cmd2name[session->cmd] : "unknown",
- session->cmd);
- }
- return ret;
- }
- D("nlmsgerr error: %u", -err->error);
-
- /* Error messages */
-
- /* Special case for IPSET_CMD_TEST */
- if (session->cmd == IPSET_CMD_TEST &&
- err->error == -IPSET_ERR_EXIST) {
- if (!(session->envopts & IPSET_ENV_QUIET)) {
- ipset_print_elem(session->report, IPSET_ERRORBUFLEN,
- session->data, IPSET_OPT_NONE, 0);
- ipset_warn(session, " is NOT in set %s.",
- ipset_data_setname(data));
- }
- return ret;
- }
-
- decode_errmsg(session, nlh);
-
- return ret;
-}
-
-static int
-callback_noop(const struct nlmsghdr *nlh UNUSED, void *data UNUSED)
-{
- return MNL_CB_OK;
-}
-/*
- * Build and send messages
- */
-
-static inline int
-open_nested(struct ipset_session *session, struct nlmsghdr *nlh, int attr)
-{
- if (nlh->nlmsg_len + MNL_ATTR_HDRLEN > session->bufsize)
- return 1;
- session->nested[session->nestid++] = mnl_attr_nest_start(nlh, attr);
- return 0;
-}
-
-static inline void
-close_nested(struct ipset_session *session, struct nlmsghdr *nlh)
-{
- mnl_attr_nest_end(nlh, session->nested[session->nestid-1]);
- session->nested[--session->nestid] = NULL;
-}
-
-static size_t
-attr_len(const struct ipset_attr_policy *attr, uint8_t family, uint16_t *flags)
-{
- switch (attr->type) {
- case MNL_TYPE_NESTED:
- if (attr->len)
- return attr->len;
-
- *flags = NLA_F_NET_BYTEORDER;
- return family == NFPROTO_IPV4 ? sizeof(uint32_t)
- : sizeof(struct in6_addr);
- case MNL_TYPE_U32:
- *flags = NLA_F_NET_BYTEORDER;
- return sizeof(uint32_t);
- case MNL_TYPE_U16:
- *flags = NLA_F_NET_BYTEORDER;
- return sizeof(uint16_t);
- case MNL_TYPE_U8:
- return sizeof(uint8_t);
- default:
- return attr->len;
- }
-}
-
-#define BUFFER_FULL(bufsize, nlmsg_len, nestlen, attrlen) \
-(nlmsg_len + nestlen + MNL_ATTR_HDRLEN + MNL_ALIGN(alen) + \
- MNL_ALIGN(sizeof(struct nlmsgerr)) > bufsize)
-
-static int
-rawdata2attr(struct ipset_session *session, struct nlmsghdr *nlh,
- const void *d, int type, uint8_t family,
- const struct ipset_attr_policy attrs[])
-{
- const struct ipset_attr_policy *attr;
- int alen;
- uint16_t flags = 0;
-
-
- attr = &attrs[type];
- if (attr->type == MNL_TYPE_NESTED) {
- /* IP addresses */
- struct nlattr *nested;
- int atype = family == NFPROTO_IPV4 ? IPSET_ATTR_IPADDR_IPV4
- : IPSET_ATTR_IPADDR_IPV6;
-
- alen = attr_len(attr, family, &flags);
- if (BUFFER_FULL(session->bufsize, nlh->nlmsg_len,
- MNL_ATTR_HDRLEN, alen))
- return 1;
- nested = mnl_attr_nest_start(nlh, type);
- D("family: %s", family == NFPROTO_IPV4 ? "INET" :
- family == NFPROTO_IPV6 ? "INET6" : "UNSPEC");
- mnl_attr_put(nlh, atype | flags, alen, d);
- mnl_attr_nest_end(nlh, nested);
-
- return 0;
- }
-
- alen = attr_len(attr, family, &flags);
- if (BUFFER_FULL(session->bufsize, nlh->nlmsg_len, 0, alen))
- return 1;
-
- switch (attr->type) {
- case MNL_TYPE_NUL_STRING:
- alen = strlen((const char *)d) + 1;
- break;
- case MNL_TYPE_U32: {
- uint32_t value = htonl(*(const uint32_t *)d);
-
- d = &value;
- break;
- }
- case MNL_TYPE_U16: {
- uint16_t value = htons(*(const uint16_t *)d);
-
- d = &value;
- break;
- }
- default:
- break;
- }
-
- mnl_attr_put(nlh, type | flags, alen, d);
-
- return 0;
-}
-
-static int
-data2attr(struct ipset_session *session, struct nlmsghdr *nlh,
- struct ipset_data *data, int type, uint8_t family,
- const struct ipset_attr_policy attrs[])
-{
- const struct ipset_attr_policy *attr = &attrs[type];
-
- return rawdata2attr(session, nlh, ipset_data_get(data, attr->opt),
- type, family, attrs);
-}
-
-#define ADDATTR_PROTOCOL(nlh) \
- mnl_attr_put_u8(nlh, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL)
-
-#define ADDATTR(session, nlh, data, type, family, attrs) \
- data2attr(session, nlh, data, type, family, attrs)
-
-#define ADDATTR_SETNAME(session, nlh, data) \
- data2attr(session, nlh, data, IPSET_ATTR_SETNAME, NFPROTO_IPV4, cmd_attrs)
-
-#define ADDATTR_IF(session, nlh, data, type, family, attrs) \
- ipset_data_test(data, attrs[type].opt) ? \
- data2attr(session, nlh, data, type, family, attrs) : 0
-
-#define ADDATTR_RAW(session, nlh, data, type, attrs) \
- rawdata2attr(session, nlh, data, type, NFPROTO_IPV4, attrs)
-
-static void
-addattr_create(struct ipset_session *session,
- struct nlmsghdr *nlh, struct ipset_data *data, uint8_t family)
-{
- int i;
-
- for (i = IPSET_ATTR_UNSPEC + 1; i <= IPSET_ATTR_CREATE_MAX; i++)
- ADDATTR_IF(session, nlh, data, i, family, create_attrs);
-}
-
-static int
-addattr_adt(struct ipset_session *session,
- struct nlmsghdr *nlh, struct ipset_data *data, uint8_t family)
-{
- int i;
-
- for (i = IPSET_ATTR_UNSPEC + 1; i <= IPSET_ATTR_ADT_MAX; i++)
- if (ADDATTR_IF(session, nlh, data, i, family, adt_attrs))
- return 1;
- return 0;
-}
-
-#define PRIVATE_MSG_BUFLEN 256
-
-static int
-build_send_private_msg(struct ipset_session *session, enum ipset_cmd cmd)
-{
- char buffer[PRIVATE_MSG_BUFLEN] __attribute__ ((aligned)) = {};
- struct nlmsghdr *nlh = (void *)buffer;
- struct ipset_data *data = session->data;
- int len = PRIVATE_MSG_BUFLEN, ret;
- enum ipset_cmd saved = session->cmd;
-
- /* Initialize header */
- session->transport->fill_hdr(session->handle, cmd, buffer, len, 0);
-
- ADDATTR_PROTOCOL(nlh);
-
- switch (cmd) {
- case IPSET_CMD_PROTOCOL:
- break;
- case IPSET_CMD_HEADER:
- if (!ipset_data_test(data, IPSET_SETNAME))
- return ipset_err(session,
- "Invalid internal HEADER command: "
- "missing setname");
- ADDATTR_SETNAME(session, nlh, data);
- break;
- case IPSET_CMD_TYPE:
- if (!ipset_data_test(data, IPSET_OPT_TYPENAME))
- return ipset_err(session,
- "Invalid internal TYPE command: "
- "missing settype");
- ADDATTR(session, nlh, data, IPSET_ATTR_TYPENAME,
- NFPROTO_IPV4, cmd_attrs);
- if (ipset_data_test(data, IPSET_OPT_FAMILY))
- ADDATTR(session, nlh, data, IPSET_ATTR_FAMILY,
- NFPROTO_IPV4, cmd_attrs);
- else
- /* bitmap:port and list:set types */
- mnl_attr_put_u8(nlh, IPSET_ATTR_FAMILY, NFPROTO_UNSPEC);
- break;
- default:
- return ipset_err(session, "Internal error: "
- "unknown private command %u", cmd);
- }
-
- /* Backup, then restore real command */
- session->cmd = cmd;
- ret = session->transport->query(session->handle, buffer, len);
- session->cmd = saved;
-
- return ret;
-}
-
-static inline bool
-may_aggregate_ad(struct ipset_session *session, enum ipset_cmd cmd)
-{
- return session->lineno != 0 &&
- (cmd == IPSET_CMD_ADD || cmd == IPSET_CMD_DEL) &&
- cmd == session->cmd &&
- STREQ(ipset_data_setname(session->data), session->saved_setname);
-}
-
-static int
-build_msg(struct ipset_session *session, bool aggregate)
-{
- struct nlmsghdr *nlh = session->buffer;
- struct ipset_data *data = session->data;
-
- /* Public commands */
- D("cmd %s, nlmsg_len: %u", cmd2name[session->cmd], nlh->nlmsg_len);
- if (nlh->nlmsg_len == 0) {
- /* Initialize header */
- aggregate = false;
- session->transport->fill_hdr(session->handle,
- session->cmd,
- session->buffer,
- session->bufsize,
- session->envopts);
- ADDATTR_PROTOCOL(nlh);
- }
- D("Protocol added, aggregate %s", aggregate ? "yes" : "no");
- switch (session->cmd) {
- case IPSET_CMD_CREATE: {
- const struct ipset_type *type;
-
- /* Sanity checkings */
- if (!ipset_data_test(data, IPSET_SETNAME))
- return ipset_err(session,
- "Invalid create command: missing setname");
- if (!ipset_data_test(data, IPSET_OPT_TYPE))
- return ipset_err(session,
- "Invalid create command: missing settype");
-
- type = ipset_data_get(data, IPSET_OPT_TYPE);
- /* Core attributes:
- * setname, typename, revision, family, flags (optional) */
- ADDATTR_SETNAME(session, nlh, data);
- ADDATTR(session, nlh, data, IPSET_ATTR_TYPENAME,
- NFPROTO_IPV4, cmd_attrs);
- ADDATTR_RAW(session, nlh, &type->revision,
- IPSET_ATTR_REVISION, cmd_attrs);
- D("family: %u, type family %u",
- ipset_data_family(data), type->family);
- if (ipset_data_test(data, IPSET_OPT_FAMILY))
- ADDATTR(session, nlh, data, IPSET_ATTR_FAMILY,
- NFPROTO_IPV4, cmd_attrs);
- else
- /* bitmap:port and list:set types */
- mnl_attr_put_u8(nlh, IPSET_ATTR_FAMILY, NFPROTO_UNSPEC);
-
- /* Type-specific create attributes */
- D("call open_nested");
- open_nested(session, nlh, IPSET_ATTR_DATA);
- addattr_create(session, nlh, data, type->family);
- D("call close_nested");
- close_nested(session, nlh);
- break;
- }
- case IPSET_CMD_DESTROY:
- case IPSET_CMD_FLUSH:
- case IPSET_CMD_SAVE:
- if (ipset_data_test(data, IPSET_SETNAME))
- ADDATTR_SETNAME(session, nlh, data);
- break;
- case IPSET_CMD_LIST: {
- uint32_t flags = 0;
-
- if (session->envopts & IPSET_ENV_LIST_SETNAME)
- flags |= IPSET_FLAG_LIST_SETNAME;
- if (session->envopts & IPSET_ENV_LIST_HEADER)
- flags |= IPSET_FLAG_LIST_HEADER;
- if (ipset_data_test(data, IPSET_SETNAME))
- ADDATTR_SETNAME(session, nlh, data);
- if (flags && session->mode != IPSET_LIST_SAVE) {
- ipset_data_set(data, IPSET_OPT_FLAGS, &flags);
- ADDATTR(session, nlh, data, IPSET_ATTR_FLAGS, NFPROTO_IPV4,
- cmd_attrs);
- }
- break;
- }
- case IPSET_CMD_RENAME:
- case IPSET_CMD_SWAP:
- if (!ipset_data_test(data, IPSET_SETNAME))
- return ipset_err(session,
- "Invalid %s command: missing from-setname",
- session->cmd == IPSET_CMD_SWAP ? "swap" :
- "rename");
- if (!ipset_data_test(data, IPSET_OPT_SETNAME2))
- return ipset_err(session,
- "Invalid %s command: missing to-setname",
- session->cmd == IPSET_CMD_SWAP ? "swap" :
- "rename");
- ADDATTR_SETNAME(session, nlh, data);
- ADDATTR_RAW(session, nlh,
- ipset_data_get(data, IPSET_OPT_SETNAME2),
- IPSET_ATTR_SETNAME2, cmd_attrs);
- break;
- case IPSET_CMD_ADD:
- case IPSET_CMD_DEL: {
- const struct ipset_type *type;
-
- if (!aggregate) {
- /* Setname, type not checked/added yet */
- if (!ipset_data_test(data, IPSET_SETNAME))
- return ipset_err(session,
- "Invalid %s command: missing setname",
- session->cmd == IPSET_CMD_ADD ? "add" :
- "del");
-
- if (!ipset_data_test(data, IPSET_OPT_TYPE))
- return ipset_err(session,
- "Invalid %s command: missing settype",
- session->cmd == IPSET_CMD_ADD ? "add" :
- "del");
-
- /* Core options: setname */
- ADDATTR_SETNAME(session, nlh, data);
- if (session->lineno != 0) {
- /* Restore mode */
- ADDATTR_RAW(session, nlh, &session->lineno,
- IPSET_ATTR_LINENO, cmd_attrs);
- open_nested(session, nlh, IPSET_ATTR_ADT);
- }
- }
- type = ipset_data_get(data, IPSET_OPT_TYPE);
- D("family: %u, type family %u",
- ipset_data_family(data), type->family);
- if (open_nested(session, nlh, IPSET_ATTR_DATA)) {
- D("open_nested failed");
- return 1;
- }
- if (addattr_adt(session, nlh, data, ipset_data_family(data)) ||
- ADDATTR_RAW(session, nlh, &session->lineno,
- IPSET_ATTR_LINENO, cmd_attrs)) {
- /* Cancel last, unfinished nested attribute */
- mnl_attr_nest_cancel(nlh,
- session->nested[session->nestid-1]);
- session->nested[--session->nestid] = NULL;
- return 1;
- }
- close_nested(session, nlh);
- break;
- }
- case IPSET_CMD_TEST: {
- const struct ipset_type *type;
- /* Return codes are not aggregated, so tests cannot be either */
-
- /* Setname, type not checked/added yet */
-
- if (!ipset_data_test(data, IPSET_SETNAME))
- return ipset_err(session,
- "Invalid test command: missing setname");
-
- if (!ipset_data_test(data, IPSET_OPT_TYPE))
- return ipset_err(session,
- "Invalid test command: missing settype");
-
- type = ipset_data_get(data, IPSET_OPT_TYPE);
- D("family: %u, type family %u",
- ipset_data_family(data), type->family);
- ADDATTR_SETNAME(session, nlh, data);
- open_nested(session, nlh, IPSET_ATTR_DATA);
- addattr_adt(session, nlh, data, ipset_data_family(data));
- close_nested(session, nlh);
- break;
- }
- default:
- return ipset_err(session, "Internal error: unknown command %u",
- session->cmd);
- }
- return 0;
-}
-
-/**
- * ipset_commit - commit buffered commands
- * @session: session structure
- *
- * Commit buffered commands, if there are any.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_commit(struct ipset_session *session)
-{
- struct nlmsghdr *nlh;
- int ret = 0, i;
-
- assert(session);
-
- nlh = session->buffer;
- D("send buffer: len %u, cmd %s",
- nlh->nlmsg_len, cmd2name[session->cmd]);
- if (nlh->nlmsg_len == 0)
- /* Nothing to do */
- return 0;
-
- /* Close nested data blocks */
- for (i = session->nestid - 1; i >= 0; i--)
- close_nested(session, nlh);
-
- /* Send buffer */
- ret = session->transport->query(session->handle,
- session->buffer,
- session->bufsize);
-
- /* Reset saved data and nested state */
- session->saved_setname[0] = '\0';
- session->printed_set = 0;
- for (i = session->nestid - 1; i >= 0; i--)
- session->nested[i] = NULL;
- session->nestid = 0;
- nlh->nlmsg_len = 0;
-
- D("ret: %d", ret);
-
- if (ret < 0) {
- if (session->report[0] != '\0')
- return -1;
- else
- return ipset_err(session,
- "Internal protocol error");
- }
- return 0;
-}
-
-static mnl_cb_t cb_ctl[] = {
- [NLMSG_NOOP] = callback_noop,
- [NLMSG_ERROR] = callback_error,
- [NLMSG_DONE] = callback_done,
- [NLMSG_OVERRUN] = callback_noop,
- [NLMSG_MIN_TYPE] = callback_data,
-};
-
-static inline struct ipset_handle *
-init_transport(struct ipset_session *session)
-{
- session->handle = session->transport->init(cb_ctl, session);
-
- return session->handle;
-}
-
-/**
- * ipset_cmd - execute a command
- * @session: session structure
- * @cmd: command to execute
- * @lineno: command line number in restore mode
- *
- * Execute - or prepare/buffer in restore mode - a command.
- * It is the caller responsibility that the data field be filled out
- * with all required parameters for a successful execution.
- * The data field is cleared after this function call for the public
- * commands.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_cmd(struct ipset_session *session, enum ipset_cmd cmd, uint32_t lineno)
-{
- struct ipset_data *data;
- bool aggregate = false;
- int ret = -1;
-
- assert(session);
-
- if (cmd <= IPSET_CMD_NONE || cmd >= IPSET_MSG_MAX)
- return 0;
-
- /* Initialize transport method if not done yet */
- if (session->handle == NULL && init_transport(session) == NULL)
- return ipset_err(session,
- "Cannot open session to kernel.");
-
- data = session->data;
-
- /* Check protocol version once */
- if (!session->version_checked) {
- if (build_send_private_msg(session, IPSET_CMD_PROTOCOL) < 0)
- return -1;
- }
-
- /* Private commands */
- if (cmd == IPSET_CMD_TYPE || cmd == IPSET_CMD_HEADER)
- return build_send_private_msg(session, cmd);
-
- /* Check aggregatable commands */
- aggregate = may_aggregate_ad(session, cmd);
- if (!aggregate) {
- /* Flush possible aggregated commands */
- ret = ipset_commit(session);
- if (ret < 0)
- return ret;
- }
-
- /* Real command: update lineno too */
- session->cmd = cmd;
- session->lineno = lineno;
-
- /* Set default output mode */
- if (cmd == IPSET_CMD_LIST) {
- if (session->mode == IPSET_LIST_NONE)
- session->mode = IPSET_LIST_PLAIN;
- } else if (cmd == IPSET_CMD_SAVE) {
- if (session->mode == IPSET_LIST_NONE)
- session->mode = IPSET_LIST_SAVE;
- }
-
- D("next: build_msg");
- /* Build new message or append buffered commands */
- ret = build_msg(session, aggregate);
- D("build_msg returned %u", ret);
- if (ret > 0) {
- /* Buffer is full, send buffered commands */
- ret = ipset_commit(session);
- if (ret < 0)
- goto cleanup;
- ret = build_msg(session, false);
- D("build_msg 2 returned %u", ret);
- }
- if (ret < 0)
- goto cleanup;
- D("past: build_msg");
-
- /* We have to save the type for error handling */
- session->saved_type = ipset_data_get(data, IPSET_OPT_TYPE);
- if (session->lineno != 0 &&
- (cmd == IPSET_CMD_ADD || cmd == IPSET_CMD_DEL)) {
- /* Save setname for the next possible aggregated restore line */
- strcpy(session->saved_setname, ipset_data_setname(data));
- ipset_data_reset(data);
- /* Don't commit: we may aggregate next command */
- ret = 0;
- goto cleanup;
- }
-
- D("call commit");
- ret = ipset_commit(session);
-
-cleanup:
- D("reset data");
- ipset_data_reset(data);
- return ret;
-}
-
-/**
- * ipset_session_init - initialize an ipset session
- *
- * Initialize an ipset session by allocating a session structure
- * and filling out with the initialization data.
- *
- * Returns the created session sctructure on success or NULL.
- */
-struct ipset_session *
-ipset_session_init(ipset_outfn outfn)
-{
- struct ipset_session *session;
- size_t bufsize = getpagesize();
-
- /* Create session object */
- session = calloc(1, sizeof(struct ipset_session) + bufsize);
- if (session == NULL)
- return NULL;
- session->bufsize = bufsize;
- session->buffer = session + 1;
-
- /* The single transport method yet */
- session->transport = &ipset_mnl_transport;
-
- /* Output function */
- session->outfn = outfn;
-
- /* Initialize data structures */
- session->data = ipset_data_init();
- if (session->data == NULL)
- goto free_session;
-
- ipset_cache_init();
- return session;
-
-free_session:
- free(session);
- return NULL;
-}
-
-/**
- * ipset_session_fini - destroy an ipset session
- * @session: session structure
- *
- * Destroy an ipset session: release the created structures.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_session_fini(struct ipset_session *session)
-{
- assert(session);
-
- if (session->handle)
- session->transport->fini(session->handle);
- if (session->data)
- ipset_data_fini(session->data);
-
- ipset_cache_fini();
- free(session);
- return 0;
-}
-
-#ifdef IPSET_DEBUG
-#include "debug.c"
-#endif
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <assert.h> /* assert */
-#include <errno.h> /* errno */
-#include <net/ethernet.h> /* ETH_ALEN */
-#include <netinet/in.h> /* struct in6_addr */
-#include <sys/socket.h> /* AF_ */
-#include <stdlib.h> /* malloc, free */
-#include <stdio.h> /* FIXME: debug */
-#include <libmnl/libmnl.h> /* MNL_ALIGN */
-
-#include <libipset/debug.h> /* D() */
-#include <libipset/data.h> /* ipset_data_* */
-#include <libipset/session.h> /* ipset_cmd */
-#include <libipset/utils.h> /* STREQ */
-#include <libipset/types.h> /* prototypes */
-
-/* Userspace cache of sets which exists in the kernel */
-
-struct ipset {
- char name[IPSET_MAXNAMELEN]; /* set name */
- const struct ipset_type *type; /* set type */
- uint8_t family; /* family */
- struct ipset *next;
-};
-
-static struct ipset_type *typelist; /* registered set types */
-static struct ipset *setlist; /* cached sets */
-
-/**
- * ipset_cache_add - add a set to the cache
- * @name: set name
- * @type: set type structure
- *
- * Add the named set to the internal cache with the specified
- * set type. The set name must be unique.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_cache_add(const char *name, const struct ipset_type *type,
- uint8_t family)
-{
- struct ipset *s, *n;
-
- assert(name);
- assert(type);
-
- n = malloc(sizeof(*n));
- if (n == NULL)
- return -ENOMEM;
-
- ipset_strlcpy(n->name, name, IPSET_MAXNAMELEN);
- n->type = type;
- n->family = family;
- n->next = NULL;
-
- if (setlist == NULL) {
- setlist = n;
- return 0;
- }
- for (s = setlist; s->next != NULL; s = s->next) {
- if (STREQ(name, s->name)) {
- free(n);
- return -EEXIST;
- }
- }
- s->next = n;
-
- return 0;
-}
-
-/**
- * ipset_cache_del - delete set from the cache
- * @name: set name
- *
- * Delete the named set from the internal cache. If NULL is
- * specified as setname, the whole cache is emptied.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_cache_del(const char *name)
-{
- struct ipset *s, *match = NULL, *prev = NULL;
-
- if (!name) {
- for (s = setlist; s != NULL; ) {
- prev = s;
- s = s->next;
- free(prev);
- }
- setlist = NULL;
- return 0;
- }
- for (s = setlist; s != NULL && match == NULL; s = s->next) {
- if (STREQ(s->name, name)) {
- match = s;
- if (prev == NULL)
- setlist = match->next;
- else
- prev->next = match->next;
- }
- prev = s;
- }
- if (match == NULL)
- return -EEXIST;
-
- free(match);
- return 0;
-}
-
-/**
- * ipset_cache_rename - rename a set in the cache
- * @from: the set to rename
- * @to: the new name of the set
- *
- * Rename the given set in the cache.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_cache_rename(const char *from, const char *to)
-{
- struct ipset *s;
-
- assert(from);
- assert(to);
-
- for (s = setlist; s != NULL; s = s->next) {
- if (STREQ(s->name, from)) {
- ipset_strlcpy(s->name, to, IPSET_MAXNAMELEN);
- return 0;
- }
- }
- return -EEXIST;
-}
-
-/**
- * ipset_cache_swap - swap two sets in the cache
- * @from: the first set
- * @to: the second set
- *
- * Swap two existing sets in the cache.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_cache_swap(const char *from, const char *to)
-{
- struct ipset *s, *a = NULL, *b = NULL;
-
- assert(from);
- assert(to);
-
- for (s = setlist; s != NULL && (a == NULL || b == NULL); s = s->next) {
- if (a == NULL && STREQ(s->name, from))
- a = s;
- if (b == NULL && STREQ(s->name, to))
- b = s;
- }
- if (a != NULL && b != NULL) {
- ipset_strlcpy(a->name, to, IPSET_MAXNAMELEN);
- ipset_strlcpy(b->name, from, IPSET_MAXNAMELEN);
- return 0;
- }
-
- return -EEXIST;
-}
-
-#define MATCH_FAMILY(type, f) \
- (f == NFPROTO_UNSPEC || type->family == f || \
- type->family == NFPROTO_IPSET_IPV46)
-
-bool
-ipset_match_typename(const char *name, const struct ipset_type *type)
-{
- const char * const *alias = type->alias;
-
- if (STREQ(name, type->name))
- return true;
-
- while (alias[0]) {
- if (STREQ(name, alias[0]))
- return true;
- alias++;
- }
- return false;
-}
-
-static inline const struct ipset_type *
-create_type_get(struct ipset_session *session)
-{
- struct ipset_type *t, *match = NULL;
- struct ipset_data *data;
- const char *typename;
- uint8_t family, tmin = 0, tmax = 0;
- uint8_t kmin, kmax;
- int ret;
-
- data = ipset_session_data(session);
- assert(data);
- typename = ipset_data_get(data, IPSET_OPT_TYPENAME);
- assert(typename);
- family = ipset_data_family(data);
-
- /* Check registered types in userspace */
- for (t = typelist; t != NULL; t = t->next) {
- /* Skip revisions which are unsupported by the kernel */
- if (t->kernel_check == IPSET_KERNEL_MISMATCH)
- continue;
- if (ipset_match_typename(typename, t)
- && MATCH_FAMILY(t, family)) {
- if (match == NULL) {
- match = t;
- tmin = tmax = t->revision;
- } else if (t->family == match->family)
- tmin = t->revision;
- }
- }
- if (!match)
- return ipset_errptr(session,
- "Syntax error: unknown settype %s",
- typename);
-
- /* Family is unspecified yet: set from matching set type */
- if (family == NFPROTO_UNSPEC && match->family != NFPROTO_UNSPEC) {
- family = match->family == NFPROTO_IPSET_IPV46 ?
- NFPROTO_IPV4 : match->family;
- ipset_data_set(data, IPSET_OPT_FAMILY, &family);
- }
-
- if (match->kernel_check == IPSET_KERNEL_OK)
- goto found;
-
- /* Check kernel */
- ret = ipset_cmd(session, IPSET_CMD_TYPE, 0);
- if (ret != 0)
- return NULL;
-
- kmin = kmax = *(const uint8_t *)ipset_data_get(data,
- IPSET_OPT_REVISION);
- if (ipset_data_test(data, IPSET_OPT_REVISION_MIN))
- 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, family %s "
- "with minimal revision %u while ipset program "
- "with maximal revision %u.\n"
- "You need to upgrade your ipset program.",
- typename,
- family == NFPROTO_IPV4 ? "INET" :
- family == NFPROTO_IPV6 ? "INET6" : "UNSPEC",
- kmin, tmax);
- else
- return ipset_errptr(session,
- "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 == NFPROTO_IPV4 ? "INET" :
- family == NFPROTO_IPV6 ? "INET6" : "UNSPEC",
- kmax, tmin);
- }
-
- /* Disable unsupported revisions */
- for (match = NULL, t = typelist; t != NULL; t = t->next) {
- /* Skip revisions which are unsupported by the kernel */
- if (t->kernel_check == IPSET_KERNEL_MISMATCH)
- continue;
- if (ipset_match_typename(typename, t)
- && MATCH_FAMILY(t, family)) {
- if (t->revision < kmin || t->revision > kmax)
- t->kernel_check = IPSET_KERNEL_MISMATCH;
- else if (match == NULL)
- match = t;
- }
- }
- match->kernel_check = IPSET_KERNEL_OK;
-found:
- ipset_data_set(data, IPSET_OPT_TYPE, match);
-
- return match;
-}
-
-#define set_family_and_type(data, match, family) do { \
- if (family == NFPROTO_UNSPEC && match->family != NFPROTO_UNSPEC) \
- family = match->family == NFPROTO_IPSET_IPV46 ? \
- NFPROTO_IPV4 : match->family;\
- ipset_data_set(data, IPSET_OPT_FAMILY, &family); \
- ipset_data_set(data, IPSET_OPT_TYPE, match); \
-} while (0)
-
-
-static inline const struct ipset_type *
-adt_type_get(struct ipset_session *session)
-{
- struct ipset_data *data;
- struct ipset *s;
- struct ipset_type *t;
- const struct ipset_type *match;
- const char *setname, *typename;
- const uint8_t *revision;
- uint8_t family = NFPROTO_UNSPEC;
- int ret;
-
- data = ipset_session_data(session);
- assert(data);
- setname = ipset_data_setname(data);
- assert(setname);
-
- /* Check existing sets in cache */
- for (s = setlist; s != NULL; s = s->next) {
- if (STREQ(setname, s->name)) {
- ipset_data_set(data, IPSET_OPT_FAMILY, &s->family);
- ipset_data_set(data, IPSET_OPT_TYPE, s->type);
- return s->type;
- }
- }
-
- /* Check kernel */
- ret = ipset_cmd(session, IPSET_CMD_HEADER, 0);
- if (ret != 0)
- return NULL;
-
- typename = ipset_data_get(data, IPSET_OPT_TYPENAME);
- revision = ipset_data_get(data, IPSET_OPT_REVISION);
- family = ipset_data_family(data);
-
- /* Check registered types */
- for (t = typelist, match = NULL;
- t != NULL && match == NULL; t = t->next) {
- if (t->kernel_check == IPSET_KERNEL_MISMATCH)
- continue;
- if (STREQ(typename, t->name)
- && MATCH_FAMILY(t, family)
- && *revision == t->revision) {
- t->kernel_check = IPSET_KERNEL_OK;
- match = t;
- }
- }
- if (!match)
- return ipset_errptr(session,
- "Kernel-library incompatibility: "
- "set %s in kernel has got settype %s "
- "with family %s and revision %u while "
- "ipset library does not support the "
- "settype with that family and revision.",
- setname, typename,
- family == NFPROTO_IPV4 ? "inet" :
- family == NFPROTO_IPV6 ? "inet6" : "unspec",
- *revision);
-
- set_family_and_type(data, match, family);
-
- return match;
-}
-
-/**
- * ipset_type_get - get a set type from the kernel
- * @session: session structure
- * @cmd: the command which needs the set type
- *
- * Build up and send a private message to the kernel in order to
- * get the set type. When creating the set, we send the typename
- * and family and get the supported revisions of the given set type.
- * When adding/deleting/testing an entry, we send the setname and
- * receive the typename, family and revision.
- *
- * Returns the set type for success and NULL for failure.
- */
-const struct ipset_type *
-ipset_type_get(struct ipset_session *session, enum ipset_cmd cmd)
-{
- assert(session);
-
- switch (cmd) {
- case IPSET_CMD_CREATE:
- return create_type_get(session);
- case IPSET_CMD_ADD:
- case IPSET_CMD_DEL:
- case IPSET_CMD_TEST:
- return adt_type_get(session);
- default:
- break;
- }
-
- assert(cmd == IPSET_CMD_NONE);
- return NULL;
-}
-
-/**
- * ipset_type_check - check the set type received from kernel
- * @session: session structure
- *
- * Check the set type received from the kernel (typename, revision,
- * family) against the userspace types looking for a matching type.
- *
- * Returns the set type for success and NULL for failure.
- */
-const struct ipset_type *
-ipset_type_check(struct ipset_session *session)
-{
- const struct ipset_type *t, *match = NULL;
- struct ipset_data *data;
- const char *typename;
- uint8_t family = NFPROTO_UNSPEC, revision;
-
- assert(session);
- data = ipset_session_data(session);
- assert(data);
-
- typename = ipset_data_get(data, IPSET_OPT_TYPENAME);
- family = ipset_data_family(data);
- revision = *(const uint8_t *) ipset_data_get(data, IPSET_OPT_REVISION);
-
- /* Check registered types */
- for (t = typelist; t != NULL && match == NULL; t = t->next) {
- if (t->kernel_check == IPSET_KERNEL_MISMATCH)
- continue;
- if (ipset_match_typename(typename, t)
- && MATCH_FAMILY(t, family)
- && t->revision == revision)
- match = t;
- }
- if (!match)
- return ipset_errptr(session,
- "Kernel and userspace incompatible: "
- "settype %s with revision %u not supported ",
- "by userspace.", typename, revision);
-
- set_family_and_type(data, match, family);
-
- return match;
-}
-
-/**
- * ipset_type_add - add (register) a userspace set type
- * @type: pointer to the set type structure
- *
- * Add the given set type to the type list. The types
- * are added sorted, in descending revision number.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_type_add(struct ipset_type *type)
-{
- struct ipset_type *t, *prev;
-
- 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)
- return -EEXIST;
- else if (t->revision < type->revision) {
- type->next = t;
- if (prev)
- prev->next = type;
- else
- typelist = type;
- return 0;
- }
- }
- if (t->next != NULL && STREQ(t->next->name, type->name)) {
- if (t->next->revision == type->revision)
- return -EEXIST;
- else if (t->next->revision < type->revision) {
- type->next = t->next;
- t->next = type;
- return 0;
- }
- }
- prev = t;
- }
- type->next = typelist;
- typelist = type;
- return 0;
-}
-
-/**
- * ipset_typename_resolve - resolve typename alias
- * @str: typename or alias
- *
- * Check the typenames (and aliases) and return the
- * preferred name of the set type.
- *
- * Returns the name of the matching set type or NULL.
- */
-const char *
-ipset_typename_resolve(const char *str)
-{
- const struct ipset_type *t;
-
- for (t = typelist; t != NULL; t = t->next)
- if (ipset_match_typename(str, t))
- return t->name;
- return NULL;
-}
-
-/**
- * ipset_types - return the list of the set types
- *
- * The types can be unchecked with respect of the running kernel.
- * Only useful for type specific help.
- *
- * Returns the list of the set types.
- */
-const struct ipset_type *
-ipset_types(void)
-{
- return typelist;
-}
-
-/**
- * ipset_cache_init - initialize set cache
- *
- * Initialize the set cache in userspace.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_cache_init(void)
-{
- return 0;
-}
-
-/**
- * ipset_cache_fini - release the set cache
- *
- * Release the set cache.
- */
-void
-ipset_cache_fini(void)
-{
- struct ipset *set;
-
- while (setlist) {
- set = setlist;
- setlist = setlist->next;
- free(set);
- }
-}
+++ /dev/null
-#include "pfxlen.h"
-
-/*
- * Prefixlen maps for fast conversions, by Jan Engelhardt.
- */
-
-#define E(a, b, c, d) \
- {.ip6 = { \
- __constant_htonl(a), __constant_htonl(b), \
- __constant_htonl(c), __constant_htonl(d), \
- } }
-
-/*
- * This table works for both IPv4 and IPv6;
- * just use prefixlen_netmask_map[prefixlength].ip.
- */
-const union nf_inet_addr ip_set_netmask_map[] = {
- E(0x00000000, 0x00000000, 0x00000000, 0x00000000),
- E(0x80000000, 0x00000000, 0x00000000, 0x00000000),
- E(0xC0000000, 0x00000000, 0x00000000, 0x00000000),
- E(0xE0000000, 0x00000000, 0x00000000, 0x00000000),
- E(0xF0000000, 0x00000000, 0x00000000, 0x00000000),
- E(0xF8000000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFC000000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFE000000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFF000000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFF800000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFC00000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFE00000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFF00000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFF80000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFC0000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFE0000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFF0000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFF8000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFC000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFE000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFF000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFF800, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFC00, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFE00, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFF00, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFF80, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFFC0, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFFE0, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFFF0, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFFF8, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFC, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFE, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0x80000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xC0000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xE0000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xF0000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xF8000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFC000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFE000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFF000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFF800000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFC00000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFE00000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFF00000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFF80000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFC0000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFE0000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFF0000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFF8000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFC000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFE000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFF000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFF800, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFC00, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFE00, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFF00, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFF80, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFC0, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFE0, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFF0, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFF8, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFC, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFE, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0x80000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xC0000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xE0000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xF0000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xF8000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFC000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFE000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFF800000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFC00000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFE00000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFF00000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFF80000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFC0000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFE0000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF0000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF8000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFC000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF800, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFC00, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFE00, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF00, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF80, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFC0, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFE0, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF0, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF8, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFC, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x80000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xC0000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xE0000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xF0000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xF8000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFC000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFE000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF800000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFC00000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFE00000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFF00000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFF80000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFC0000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFE0000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF0000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF8000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFC000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF800),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFC00),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFE00),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF00),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF80),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFC0),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFE0),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF0),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF8),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFC),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF),
-};
-EXPORT_SYMBOL_GPL(ip_set_netmask_map);
-
-#undef E
-#define E(a, b, c, d) \
- {.ip6 = { (__force __be32) a, (__force __be32) b, \
- (__force __be32) c, (__force __be32) d, \
- } }
-
-/*
- * This table works for both IPv4 and IPv6;
- * just use prefixlen_hostmask_map[prefixlength].ip.
- */
-const union nf_inet_addr ip_set_hostmask_map[] = {
- E(0x00000000, 0x00000000, 0x00000000, 0x00000000),
- E(0x80000000, 0x00000000, 0x00000000, 0x00000000),
- E(0xC0000000, 0x00000000, 0x00000000, 0x00000000),
- E(0xE0000000, 0x00000000, 0x00000000, 0x00000000),
- E(0xF0000000, 0x00000000, 0x00000000, 0x00000000),
- E(0xF8000000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFC000000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFE000000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFF000000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFF800000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFC00000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFE00000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFF00000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFF80000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFC0000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFE0000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFF0000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFF8000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFC000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFE000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFF000, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFF800, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFC00, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFE00, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFF00, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFF80, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFFC0, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFFE0, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFFF0, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFFF8, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFC, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFE, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0x80000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xC0000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xE0000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xF0000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xF8000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFC000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFE000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFF000000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFF800000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFC00000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFE00000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFF00000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFF80000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFC0000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFE0000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFF0000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFF8000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFC000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFE000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFF000, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFF800, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFC00, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFE00, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFF00, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFF80, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFC0, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFE0, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFF0, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFF8, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFC, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFE, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0x80000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xC0000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xE0000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xF0000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xF8000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFC000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFE000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFF800000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFC00000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFE00000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFF00000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFF80000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFC0000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFE0000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF0000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF8000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFC000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF000, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF800, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFC00, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFE00, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF00, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF80, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFC0, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFE0, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF0, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF8, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFC, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x80000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xC0000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xE0000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xF0000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xF8000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFC000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFE000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF000000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFF800000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFC00000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFE00000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFF00000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFF80000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFC0000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFE0000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF0000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFF8000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFC000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF000),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFF800),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFC00),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFE00),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF00),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF80),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFC0),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFE0),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF0),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFF8),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFC),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE),
- E(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF),
-};
-EXPORT_SYMBOL_GPL(ip_set_hostmask_map);
-
-/* Find the largest network which matches the range from left, in host order. */
-u32
-ip_set_range_to_cidr(u32 from, u32 to, u8 *cidr)
-{
- u32 last;
- u8 i;
-
- for (i = 1; i < 32; i++) {
- if ((from & ip_set_hostmask(i)) != from)
- continue;
- last = from | ~ip_set_hostmask(i);
- if (!after(last, to)) {
- *cidr = i;
- return last;
- }
- }
- *cidr = 32;
- return from;
-}
-EXPORT_SYMBOL_GPL(ip_set_range_to_cidr);
+++ /dev/null
-#ifndef _PFXLEN_H
-#define _PFXLEN_H
-
-#include <asm/byteorder.h>
-#include <linux/netfilter.h>
-#include <net/tcp.h>
-
-/* Prefixlen maps, by Jan Engelhardt */
-extern const union nf_inet_addr ip_set_netmask_map[];
-extern const union nf_inet_addr ip_set_hostmask_map[];
-
-static inline __be32
-ip_set_netmask(u8 pfxlen)
-{
- return ip_set_netmask_map[pfxlen].ip;
-}
-
-static inline const __be32 *
-ip_set_netmask6(u8 pfxlen)
-{
- return &ip_set_netmask_map[pfxlen].ip6[0];
-}
-
-static inline u32
-ip_set_hostmask(u8 pfxlen)
-{
- return (__force u32) ip_set_hostmask_map[pfxlen].ip;
-}
-
-static inline const __be32 *
-ip_set_hostmask6(u8 pfxlen)
-{
- return &ip_set_hostmask_map[pfxlen].ip6[0];
-}
-
-extern u32 ip_set_range_to_cidr(u32 from, u32 to, u8 *cidr);
-
-#define ip_set_mask_from_to(from, to, cidr) \
-do { \
- from &= ip_set_hostmask(cidr); \
- to = from | ~ip_set_hostmask(cidr); \
-} while (0)
-
-#endif /*_PFXLEN_H */
+++ /dev/null
-.\" Man page written by Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
-.\"
-.\" This program is free software; you can redistribute it and/or modify
-.\" it under the terms of the GNU General Public License as published by
-.\" the Free Software Foundation; either version 2 of the License, or
-.\" (at your option) any later version.
-.\"
-.\" This program is distributed in the hope that it will be useful,
-.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
-.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-.\" GNU General Public License for more details.
-.\"
-.\" You should have received a copy of the GNU General Public License
-.\" along with this program; if not, write to the Free Software
-.\" Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-.TH "IPSET" "8" "Oct 15, 2010" "Jozsef Kadlecsik" ""
-.SH "NAME"
-ipset \(em administration tool for IP sets
-.SH "SYNOPSIS"
-\fBipset\fR [ \fIOPTIONS\fR ] \fICOMMAND\fR [ \fICOMMAND\-OPTIONS\fR ]
-.PP
-COMMANDS := { \fBcreate\fR | \fBadd\fR | \fBdel\fR | \fBtest\fR | \fBdestroy\fR | \fBlist\fR | \fBsave\fR | \fBrestore\fR | \fBflush\fR | \fBrename\fR | \fBswap\fR | \fBhelp\fR | \fBversion\fR | \fB\-\fR }
-.PP
-\fIOPTIONS\fR := { \fB\-exist\fR | \fB\-output\fR { \fBplain\fR | \fBsave\fR | \fBxml\fR } | \fB\-quiet\fR | \fB\-resolve\fR | \fB\-sorted\fR | \fB\-name\fR | \fB\-terse\fR }
-.PP
-\fBipset\fR \fBcreate\fR \fISETNAME\fR \fITYPENAME\fR [ \fICREATE\-OPTIONS\fR ]
-.PP
-\fBipset\fR \fBadd\fR \fISETNAME\fR \fIADD\-ENTRY\fR [ \fIADD\-OPTIONS\fR ]
-.PP
-\fBipset\fR \fBdel\fR \fISETNAME\fR \fIDEL\-ENTRY\fR [ \fIDEL\-OPTIONS\fR ]
-.PP
-\fBipset\fR \fBtest\fR \fISETNAME\fR \fITEST\-ENTRY\fR [ \fITEST\-OPTIONS\fR ]
-.PP
-\fBipset\fR \fBdestroy\fR [ \fISETNAME\fR ]
-.PP
-\fBipset\fR \fBlist\fR [ \fISETNAME\fR ]
-.PP
-\fBipset\fR \fBsave\fR [ \fISETNAME\fR ]
-.PP
-\fBipset\fR \fBrestore\fR
-.PP
-\fBipset\fR \fBflush\fR [ \fISETNAME\fR ]
-.PP
-\fBipset\fR \fBrename\fR \fISETNAME\-FROM\fR \fISETNAME\-TO\fR
-.PP
-\fBipset\fR \fBswap\fR \fISETNAME\-FROM\fR \fISETNAME\-TO\fR
-.PP
-\fBipset\fR \fBhelp\fR [ \fITYPENAME\fR ]
-.PP
-\fBipset\fR \fBversion\fR
-.PP
-\fBipset\fR \fB\-\fR
-.SH "DESCRIPTION"
-\fBipset\fR
-is used to set up, maintain and inspect so called IP sets in the Linux
-kernel. Depending on the type of the set, an IP set may store IP(v4/v6)
-addresses, (TCP/UDP) port numbers, IP and MAC address pairs, IP address
-and port number pairs, etc. See the set type definitions below.
-.PP
-\fBIptables\fR
-matches and targets referring to sets create references, which
-protect the given sets in the kernel. A set cannot be destroyed
-while there is a single reference pointing to it.
-.SH "OPTIONS"
-The options that are recognized by
-\fBipset\fR
-can be divided into several different groups.
-.SS COMMANDS
-These options specify the desired action to perform. Only one of them
-can be specified on the command line unless otherwise specified below.
-For all the long versions of the command names, you need to use only enough
-letters to ensure that
-\fBipset\fR
-can differentiate it from all other commands. The
-\fBipset\fR
-parser follows the order here when looking for the shortest match
-in the long command names.
-.TP
-\fBn\fP, \fBcreate\fP \fISETNAME\fP \fITYPENAME\fP [ \fICREATE\-OPTIONS\fP ]
-Create a set identified with setname and specified type. The type may require
-type specific options. If the
-\fB\-exist\fR
-option is specified,
-\fBipset\fR
-ignores the error otherwise raised when the same set (setname and create parameters
-are identical) already exists.
-.TP
-\fBadd\fP \fISETNAME\fP \fIADD\-ENTRY\fP [ \fIADD\-OPTIONS\fP ]
-Add a given entry to the set. If the
-\fB\-exist\fR
-option is specified,
-\fBipset\fR
-ignores if the entry already added to the set.
-.TP
-\fBdel\fP \fISETNAME\fP \fIDEL\-ENTRY\fP [ \fIDEL\-OPTIONS\fP ]
-Delete an entry from a set. If the
-\fB\-exist\fR
-option is specified,
-\fBipset\fR
-ignores if the entry does not added to (already expired from) the set.
-.TP
-\fBtest\fP \fISETNAME\fP \fITEST\-ENTRY\fP [ \fITEST\-OPTIONS\fP ]
-Test wether an entry is in a set or not. Exit status number is zero
-if the tested entry is in the set and nonzero if it is missing from
-the set.
-.TP
-\fBx\fP, \fBdestroy\fP [ \fISETNAME\fP ]
-Destroy the specified set or all the sets if none is given.
-
-If the set has got reference(s), nothing is done and no set destroyed.
-.TP
-\fBlist\fP [ \fISETNAME\fP ] [ \fIOPTIONS\fP ]
-List the header data and the entries for the specified set, or for
-all sets if none is given. The
-\fB\-resolve\fP
-option can be used to force name lookups (which may be slow). When the
-\fB\-sorted\fP
-option is given, the entries are listed sorted (if the given set
-type supports the operation). The option
-\fB\-output\fR
-can be used to control the format of the listing:
-\fBplain\fR, \fBsave\fR or \fBxml\fR.
-(The default is
-\fBplain\fR.)
-If the option
-\fB\-name\fR
-is specified, just the names of the existing sets are listed. If the option
-\fB\-terse\fR
-is specified, just the set names and headers are listed.
-.TP
-\fBsave\fP [ \fISETNAME\fP ]
-Save the given set, or all sets if none is given
-to stdout in a format that
-\fBrestore\fP
-can read.
-.TP
-\fBrestore\fP
-Restore a saved session generated by
-\fBsave\fP.
-The saved session can be fed from stdin.
-.TP
-\fBflush\fP [ \fISETNAME\fP ]
-Flush all entries from the specified set or flush
-all sets if none is given.
-.TP
-\fBe\fP, \fBrename\fP \fISETNAME\-FROM\fP \fISETNAME\-TO\fP
-Rename a set. Set identified by
-\fISETNAME\-TO\fR
-must not exist.
-.TP
-\fBw\fP, \fBswap\fP \fISETNAME\-FROM\fP \fISETNAME\-TO\fP
-Swap the content of two sets, or in another words,
-exchange the name of two sets. The referred sets must exist and
-identical type of sets can be swapped only.
-.TP
-\fBhelp\fP [ \fITYPENAME\fP ]
-Print help and set type specific help if
-\fITYPENAME\fR
-is specified.
-.TP
-\fBversion\fP
-Print program version.
-.TP
-\fB\-\fP
-If a dash is specified as command, then
-\fBipset\fR
-enters a simple interactive mode and the commands are read from the standard input.
-The interactive mode can be finished by entering the pseudo\-command
-\fBquit\fR.
-.P
-.SS "OTHER OPTIONS"
-The following additional options can be specified. The long option names
-cannot be abbreviated.
-.TP
-\fB\-!\fP, \fB\-exist\fP
-Ignore errors when the exactly the same set is to be created or already
-added entry is added or missing entry is deleted.
-.TP
-\fB\-o\fP, \fB\-output\fP { \fBplain\fR | \fBsave\fR | \fBxml\fR }
-Select the output format to the
-\fBlist\fR
-command.
-.TP
-\fB\-q\fP, \fB\-quiet\fP
-Suppress any output to stdout and stderr.
-\fBipset\fR
-will still exit with error if it cannot continue.
-.TP
-\fB\-r\fP, \fB\-resolve\fP
-When listing sets, enforce name lookup. The
-program will try to display the IP entries resolved to
-host names which requires
-\fBslow\fR
-DNS lookups.
-.TP
-\fB\-s\fP, \fB\-sorted\fP
-Sorted output. When listing sets entries are listed sorted. Not supported yet.
-.TP
-\fB\-n\fP, \fB\-name\fP
-List just the names of the existing sets, i.e. suppress listing of set headers and members.
-.TP
-\fB\-t\fP, \fB\-terse\fP
-List the set names and headers, i.e. suppress listing of set members.
-
-.SH "SET TYPES"
-A set type comprises of the storage method by which the data is stored and
-the data type(s) which are stored in the set. Therefore the
-\fITYPENAME\fR
-parameter of the
-\fBcreate\fR
-command follows the syntax
-
-\fITYPENAME\fR := \fImethod\fR\fB:\fR\fIdatatype\fR[\fB,\fR\fIdatatype\fR[\fB,\fR\fIdatatype\fR]]
-
-where the current list of the methods are
-\fBbitmap\fR, \fBhash\fR, and \fBlist\fR and the possible data types
-are \fBip\fR, \fBnet\fR, \fBmac\fR, \fBport\fR and \fBiface\fR.
-The dimension of a set is equal to the number of data types in its type name.
-
-When adding, deleting or testing entries in a set, the same comma separated
-data syntax must be used for the entry parameter of the commands, i.e
-
-ipset add foo ipaddr,portnum,ipaddr
-
-The \fBbitmap\fR and \fBlist\fR types use a fixed sized storage. The \fBhash\fR
-types use a hash to store the elements. In order to avoid clashes in the hash,
-a limited number of chaining, and if that is exhausted, the doubling of the hash size
-is performed when adding entries by the
-\fBipset\fR
-command. When entries added by the
-\fBSET\fR
-target of
-\fBiptables/ip6tables\fR,
-then the hash size is fixed and the set won't be duplicated, even if the new
-entry cannot be added to the set.
-
-All set types support the optional
-
-\fBtimeout\fR \fIvalue\fR
-
-parameter when creating a set and adding entries. The value of the \fBtimeout\fR
-parameter for the \fBcreate\fR command means the default timeout value (in seconds)
-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
-to 65536 entries.
-.PP
-\fICREATE\-OPTIONS\fR := \fBrange\fP \fIfromip\fP\-\fItoip\fR|\fIip\fR/\fIcidr\fR [ \fBnetmask\fP \fIcidr\fP ] [ \fBtimeout\fR \fIvalue\fR ]
-.PP
-\fIADD\-ENTRY\fR := { \fIip\fR | \fIfromip\fR\-\fItoip\fR | \fIip\fR/\fIcidr\fR }
-.PP
-\fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ]
-.PP
-\fIDEL\-ENTRY\fR := { \fIip\fR | \fIfromip\fR\-\fItoip\fR | \fIip\fR/\fIcidr\fR }
-.PP
-\fITEST\-ENTRY\fR := \fIip\fR
-.PP
-Mandatory \fBcreate\fR options:
-.TP
-\fBrange\fP \fIfromip\fP\-\fItoip\fR|\fIip\fR/\fIcidr\fR
-Create the set from the specified inclusive address range expressed in an
-IPv4 address range or network. The size of the range (in entries) cannot exceed
-the limit of maximum 65536 elements.
-.PP
-Optional \fBcreate\fR options:
-.TP
-\fBnetmask\fP \fIcidr\fP
-When the optional \fBnetmask\fP parameter specified, network addresses will be
-stored in the set instead of IP host addresses. The \fIcidr\fR prefix value must be
-between 1\-32.
-An IP address will be in the set if the network address, which is resulted by
-masking the address with the specified netmask calculated from the prefix,
-can be found in the set.
-.PP
-The \fBbitmap:ip\fR type supports adding or deleting multiple entries in one
-command.
-.PP
-Examples:
-.IP
-ipset create foo bitmap:ip range 192.168.0.0/16
-.IP
-ipset add foo 192.168.1/24
-.IP
-ipset test foo 192.168.1.1
-.SS bitmap:ip,mac
-The \fBbitmap:ip,mac\fR set type uses a memory range to store IPv4 and a MAC address pairs. A \fBbitmap:ip,mac\fR type of set can store up to 65536 entries.
-.PP
-\fICREATE\-OPTIONS\fR := \fBrange\fP \fIfromip\fP\-\fItoip\fR|\fIip\fR/\fIcidr\fR [ \fBtimeout\fR \fIvalue\fR ]
-.PP
-\fIADD\-ENTRY\fR := \fIip\fR[,\fImacaddr\fR]
-.PP
-\fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ]
-.PP
-\fIDEL\-ENTRY\fR := \fIip\fR[,\fImacaddr\fR]
-.PP
-\fITEST\-ENTRY\fR := \fIip\fR[,\fImacaddr\fR]
-.PP
-Mandatory options to use when creating a \fBbitmap:ip,mac\fR type of set:
-.TP
-\fBrange\fP \fIfromip\fP\-\fItoip\fR|\fIip\fR/\fIcidr\fR
-Create the set from the specified inclusive address range expressed in an
-IPv4 address range or network. The size of the range cannot exceed the limit
-of maximum 65536 entries.
-.PP
-The \fBbitmap:ip,mac\fR type is exceptional in the sense that the MAC part can
-be left out when adding/deleting/testing entries in the set. If we add an entry
-without the MAC address specified, then when the first time the entry is
-matched by the kernel, it will automatically fill out the missing MAC address with the
-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
-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
-ipset create foo bitmap:ip,mac range 192.168.0.0/16
-.IP
-ipset add foo 192.168.1.1,12:34:56:78:9A:BC
-.IP
-ipset test foo 192.168.1.1
-.SS bitmap:port
-The \fBbitmap:port\fR set type uses a memory range to store port numbers
-and such a set can store up to 65536 ports.
-.PP
-\fICREATE\-OPTIONS\fR := \fBrange\fP \fIfromport\fP\-\fItoport [ \fBtimeout\fR \fIvalue\fR ]
-.PP
-\fIADD\-ENTRY\fR := { \fIport\fR | \fIfromport\fR\-\fItoport\fR }
-.PP
-\fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ]
-.PP
-\fIDEL\-ENTRY\fR := { \fIport\fR | \fIfromport\fR\-\fItoport\fR }
-.PP
-\fITEST\-ENTRY\fR := \fIport\fR
-.PP
-Mandatory options to use when creating a \fBbitmap:port\fR type of set:
-.TP
-\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
-.IP
-ipset add foo 80
-.IP
-ipset test foo 80
-.SS hash:ip
-The \fBhash:ip\fR set type uses a hash to store IP host addresses (default) or
-network addresses. Zero valued IP address cannot be stored in a \fBhash:ip\fR
-type of set.
-.PP
-\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBnetmask\fP \fIcidr\fP ] [ \fBtimeout\fR \fIvalue\fR ]
-.PP
-\fIADD\-ENTRY\fR := \fIipaddr\fR
-.PP
-\fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ]
-.PP
-\fIDEL\-ENTRY\fR := \fIipaddr\fR
-.PP
-\fITEST\-ENTRY\fR := \fIipaddr\fR
-.PP
-Optional \fBcreate\fR options:
-.TP
-\fBfamily\fR { \fBinet\fR | \fBinet6\fR }
-The protocol family of the IP addresses to be stored in the set. The default is
-\fBinet\fR, i.e IPv4.
-.TP
-\fBhashsize\fR \fIvalue\fR
-The initial hash size for the set, default is 1024. The hash size must be a power
-of two, the kernel automatically rounds up non power of two hash sizes to the first
-correct value.
-.TP
-\fBmaxelem\fR \fIvalue\fR
-The maximal number of elements which can be stored in the set, default 65536.
-.TP
-\fBnetmask\fP \fIcidr\fP
-When the optional \fBnetmask\fP parameter specified, network addresses will be
-stored in the set instead of IP host addresses. The \fIcidr\fP prefix value must be
-between 1\-32 for IPv4 and between 1\-128 for IPv6. An IP address will be in the set
-if the network address, which is resulted by masking the address with the netmask
-calculated from the prefix, can be found in the set.
-.PP
-For the \fBinet\fR family one can add or delete multiple entries by specifying
-a range or a network:
-.PP
-\fIipaddr\fR := { \fIip\fR | \fIfromaddr\fR\-\fItoaddr\fR | \fIip\fR/\fIcidr\fR }
-.PP
-Examples:
-.IP
-ipset create foo hash:ip netmask 30
-.IP
-ipset add foo 192.168.1.0/24
-.IP
-ipset test foo 192.168.1.2
-.SS hash:net
-The \fBhash:net\fR set type uses a hash to store different sized IP network addresses.
-Network address with zero prefix size cannot be stored in this type of sets.
-.PP
-\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ]
-.PP
-\fIADD\-ENTRY\fR := \fInetaddr\fR
-.PP
-\fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ]
-.PP
-\fIDEL\-ENTRY\fR := \fInetaddr\fR
-.PP
-\fITEST\-ENTRY\fR := \fInetaddr\fR
-.PP
-where
-\fInetaddr\fR := \fIip\fR[/\fIcidr\fR]
-.PP
-Optional \fBcreate\fR options:
-.TP
-\fBfamily\fR { \fBinet\fR | \fBinet6\fR }
-The protocol family of the IP addresses to be stored in the set. The default is
-\fBinet\fR, i.e IPv4.
-.TP
-\fBhashsize\fR \fIvalue\fR
-The initial hash size for the set, default is 1024. The hash size must be a power
-of two, the kernel automatically rounds up non power of two hash sizes to the first
-correct value.
-.TP
-\fBmaxelem\fR \fIvalue\fR
-The maximal number of elements which can be stored in the set, default 65536.
-.PP
-For the \fBinet\fR family one can add or delete multiple entries by specifying
-a range, which is converted internally to network(s) equal to the range:
-.PP
-\fInetaddr\fR := { \fIip\fR[/\fIcidr\fR] | \fIfromaddr\fR\-\fItoaddr\fR }
-.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, 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
-prefix) to the largest one (least specific prefix) added to the set.
-When adding/deleting IP addresses to the set by the \fBSET\fR netfilter target,
-it will be added/deleted by the most specific prefix which can be found in the
-set, or by the host prefix value if the set is empty.
-.PP
-The lookup time grows linearly with the number of the different prefix
-values added to the set.
-.PP
-Examples:
-.IP
-ipset create foo hash:net
-.IP
-ipset add foo 192.168.0.0/24
-.IP
-ipset add foo 10.1.0.0/16
-.IP
-ipset test foo 192.168.0/24
-.SS hash:ip,port
-The \fBhash:ip,port\fR set type uses a hash to store IP address and port number pairs.
-The port number is interpreted together with a protocol (default TCP) and zero
-protocol number cannot be used.
-.PP
-\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ]
-.PP
-\fIADD\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR
-.PP
-\fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ]
-.PP
-\fIDEL\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR
-.PP
-\fITEST\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR
-.PP
-Optional \fBcreate\fR options:
-.TP
-\fBfamily\fR { \fBinet\fR | \fBinet6\fR }
-The protocol family of the IP addresses to be stored in the set. The default is
-\fBinet\fR, i.e IPv4.
-.TP
-\fBhashsize\fR \fIvalue\fR
-The initial hash size for the set, default is 1024. The hash size must be a power
-of two, the kernel automatically rounds up non power of two hash sizes to the first
-correct value
-.TP
-\fBmaxelem\fR \fIvalue\fR
-The maximal number of elements which can be stored in the set, default 65536.
-.PP
-For the \fBinet\fR family one can add or delete multiple entries by specifying
-a range or a network of IPv4 addresses in the IP address part of the entry:
-.PP
-\fIipaddr\fR := { \fIip\fR | \fIfromaddr\fR\-\fItoaddr\fR | \fIip\fR/\fIcidr\fR }
-.PP
-The
-[\fIproto\fR:]\fIport\fR
-part of the elements may be expressed in the following forms, where the range
-variations are valid when adding or deleting entries:
-.TP
-\fIportname[\-portname]\fR
-TCP port or range of ports expressed in TCP portname identifiers from /etc/services
-.TP
-\fIportnumber[\-portnumber]\fR
-TCP port or range of ports expressed in TCP port numbers
-.TP
-\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
-be listed by the help command.
-.TP
-\fBicmpv6\fR:\fIcodename\fR|\fItype\fR/\fIcode\fR
-ICMPv6 codename or type/code. The supported ICMPv6 codename identifiers can always
-be listed by the help command.
-.TP
-\fIproto\fR:0
-All other protocols, as an identifier from /etc/protocols or number. The pseudo
-port number must be zero.
-.PP
-The \fBhash:ip,port\fR type of sets require
-two \fBsrc\fR/\fBdst\fR parameters of the \fBset\fR match and \fBSET\fR
-target kernel modules.
-.PP
-Examples:
-.IP
-ipset create foo hash:ip,port
-.IP
-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,vrrp:0
-.IP
-ipset test foo 192.168.1.1,80
-.SS hash:net,port
-The \fBhash:net,port\fR set type uses a hash to store different sized IP network
-address and port pairs. The port number is interpreted together with a protocol
-(default TCP) and zero protocol number cannot be used. Network
-address with zero prefix size is not accepted either.
-.PP
-\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ]
-.PP
-\fIADD\-ENTRY\fR := \fInetaddr\fR,[\fIproto\fR:]\fIport\fR
-.PP
-\fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ]
-.PP
-\fIDEL\-ENTRY\fR := \fInetaddr\fR,[\fIproto\fR:]\fIport\fR
-.PP
-\fITEST\-ENTRY\fR := \fInetaddr\fR,[\fIproto\fR:]\fIport\fR
-.PP
-where
-\fInetaddr\fR := \fIip\fR[/\fIcidr\fR]
-.PP
-Optional \fBcreate\fR options:
-.TP
-\fBfamily\fR { \fBinet\fR | \fBinet6\fR }
-The protocol family of the IP addresses to be stored in the set. The default is
-\fBinet\fR, i.e IPv4.
-.TP
-\fBhashsize\fR \fIvalue\fR
-The initial hash size for the set, default is 1024. The hash size must be a power
-of two, the kernel automatically rounds up non power of two hash sizes to the first
-correct value.
-.TP
-\fBmaxelem\fR \fIvalue\fR
-The maximal number of elements which can be stored in the set, default 65536.
-.PP
-For the \fInetaddr\fR part of the elements
-see the description at the \fBhash:net\fR set type. For the
-[\fIproto\fR:]\fIport\fR
-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, 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
-prefix) to the largest one (least specific prefix) added to the set.
-When adding/deleting IP
-addresses to the set by the \fBSET\fR netfilter target, it will be
-added/deleted by the most specific prefix which can be found in the
-set, or by the host prefix value if the set is empty.
-.PP
-The lookup time grows linearly with the number of the different prefix
-values added to the set.
-.PP
-Examples:
-.IP
-ipset create foo hash:net,port
-.IP
-ipset add foo 192.168.0/24,25
-.IP
-ipset add foo 10.1.0.0/16,80
-.IP
-ipset test foo 192.168.0/24,25
-.SS hash:ip,port,ip
-The \fBhash:ip,port,ip\fR set type uses a hash to store IP address, port number
-and a second IP address triples. The port number is interpreted together with a
-protocol (default TCP) and zero protocol number cannot be used.
-.PP
-\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ]
-.PP
-\fIADD\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR,\fIip\fR
-.PP
-\fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ]
-.PP
-\fIDEL\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR,\fIip\fR
-.PP
-\fITEST\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR,\fIip\fR
-.PP
-For the first \fIipaddr\fR and
-[\fIproto\fR:]\fIport\fR
-parts of the elements see the descriptions at the
-\fBhash:ip,port\fR set type.
-.PP
-Optional \fBcreate\fR options:
-.TP
-\fBfamily\fR { \fBinet\fR | \fBinet6\fR }
-The protocol family of the IP addresses to be stored in the set. The default is
-\fBinet\fR, i.e IPv4.
-.TP
-\fBhashsize\fR \fIvalue\fR
-The initial hash size for the set, default is 1024. The hash size must be a power
-of two, the kernel automatically rounds up non power of two hash sizes to the first
-correct value.
-.TP
-\fBmaxelem\fR \fIvalue\fR
-The maximal number of elements which can be stored in the set, default 65536.
-.PP
-The \fBhash:ip,port,ip\fR type of sets require
-three \fBsrc\fR/\fBdst\fR parameters of the \fBset\fR match and \fBSET\fR
-target kernel modules.
-.PP
-Examples:
-.IP
-ipset create foo hash:ip,port,ip
-.IP
-ipset add foo 192.168.1.1,80,10.0.0.1
-.IP
-ipset test foo 192.168.1.1,udp:53,10.0.0.1
-.SS hash:ip,port,net
-The \fBhash:ip,port,net\fR set type uses a hash to store IP address, port number
-and IP network address triples. The port number is interpreted together with a
-protocol (default TCP) and zero protocol number cannot be used. Network
-address with zero prefix size cannot be stored either.
-.PP
-\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ]
-.PP
-\fIADD\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR,\fInetaddr\fR
-.PP
-\fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ]
-.PP
-\fIDEL\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR,\fInetaddr\fR
-.PP
-\fITEST\-ENTRY\fR := \fIipaddr\fR,[\fIproto\fR:]\fIport\fR,\fInetaddr\fR
-.PP
-where
-\fInetaddr\fR := \fIip\fR[/\fIcidr\fR]
-.PP
-For the \fIipaddr\fR and
-[\fIproto\fR:]\fIport\fR
-parts of the elements see the descriptions at the
-\fBhash:ip,port\fR set type. For the \fInetaddr\fR part of the elements
-see the description at the \fBhash:net\fR set type.
-.PP
-Optional \fBcreate\fR options:
-.TP
-\fBfamily\fR { \fBinet\fR | \fBinet6\fR }
-The protocol family of the IP addresses to be stored in the set. The default is
-\fBinet\fR, i.e IPv4.
-.TP
-\fBhashsize\fR \fIvalue\fR
-The initial hash size for the set, default is 1024. The hash size must be a power
-of two, the kernel automatically rounds up non power of two hash sizes to the first
-correct value.
-.TP
-\fBmaxelem\fR \fIvalue\fR
-The maximal number of elements which can be stored in the set, default 65536.
-.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
-cidr) to the largest one (least specific cidr) added to the set.
-When adding/deleting triples
-to the set by the \fBSET\fR netfilter target, it will be
-added/deleted by the most specific cidr which can be found in the
-set, or by the host cidr value if the set is empty.
-.PP
-The lookup time grows linearly with the number of the different \fIcidr\fR
-values added to the set.
-.PP
-The \fBhash:ip,port,net\fR type of sets require three \fBsrc\fR/\fBdst\fR parameters of
-the \fBset\fR match and \fBSET\fR target kernel modules.
-.PP
-Examples:
-.IP
-ipset create foo hash:ip,port,net
-.IP
-ipset add foo 192.168.1,80,10.0.0/24
-.IP
-ipset add foo 192.168.2,25,10.1.0.0/16
-.IP
-ipset test foo 192.168.1,80.10.0.0/24
-.SS hash:net,iface
-The \fBhash:net,iface\fR set type uses a hash to store different sized IP network
-address and interface name pairs. Network address with zero prefix size is not
-accepted.
-.PP
-\fICREATE\-OPTIONS\fR := [ \fBfamily\fR { \fBinet\fR | \fBinet6\fR } ] | [ \fBhashsize\fR \fIvalue\fR ] [ \fBmaxelem\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ]
-.PP
-\fIADD\-ENTRY\fR := \fInetaddr\fR,[\fBphysdev\fR:]\fIiface\fR
-.PP
-\fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ]
-.PP
-\fIDEL\-ENTRY\fR := \fInetaddr\fR,[\fBphysdev\fR:]\fIiface\fR
-.PP
-\fITEST\-ENTRY\fR := \fInetaddr\fR,[\fBphysdev\fR:]\fIiface\fR
-.PP
-where
-\fInetaddr\fR := \fIip\fR[/\fIcidr\fR]
-.PP
-Optional \fBcreate\fR options:
-.TP
-\fBfamily\fR { \fBinet\fR | \fBinet6\fR }
-The protocol family of the IP addresses to be stored in the set. The default is
-\fBinet\fR, i.e IPv4.
-.TP
-\fBhashsize\fR \fIvalue\fR
-The initial hash size for the set, default is 1024. The hash size must be a power
-of two, the kernel automatically rounds up non power of two hash sizes to the first
-correct value.
-.TP
-\fBmaxelem\fR \fIvalue\fR
-The maximal number of elements which can be stored in the set, default 65536.
-.PP
-For the \fInetaddr\fR part of the elements
-see the description at the \fBhash:net\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, 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
-prefix) to the largest one (least specific prefix) added to the set.
-When adding/deleting IP
-addresses to the set by the \fBSET\fR netfilter target, it will be
-added/deleted by the most specific prefix which can be found in the
-set, or by the host prefix value if the set is empty.
-.PP
-The second direction parameter of the \fBset\fR match and
-\fBSET\fR target modules corresponds to the incoming/outgoing interface
-: \fBsrc\fR to the incoming, while \fBdst\fR to the outgoing. When
-the interface is flagged with \fBphysdev:\fR, the interface is interpreted
-as the incoming/outgoing bridge port.
-.PP
-The lookup time grows linearly with the number of the different prefix
-values added to the set.
-.PP
-The internal restriction of the \fBhash:net,iface\fR set type is that
-the same network prefix cannot be stored with more than 64 different interfaces
-in a single set.
-.PP
-Examples:
-.IP
-ipset create foo hash:net,iface
-.IP
-ipset add foo 192.168.0/24,eth0
-.IP
-ipset add foo 10.1.0.0/16,eth1
-.IP
-ipset test foo 192.168.0/24,eth0
-.SS list:set
-The \fBlist:set\fR type uses a simple list in which you can store
-set names.
-.PP
-\fICREATE\-OPTIONS\fR := [ \fBsize\fR \fIvalue\fR ] [ \fBtimeout\fR \fIvalue\fR ]
-.PP
-\fIADD\-ENTRY\fR := \fIsetname\fR [ { \fBbefore\fR | \fBafter\fR } \fIsetname\fR ]
-.PP
-\fIADD\-OPTIONS\fR := [ \fBtimeout\fR \fIvalue\fR ]
-.PP
-\fIDEL\-ENTRY\fR := \fIsetname\fR [ { \fBbefore\fR | \fBafter\fR } \fIsetname\fR ]
-.PP
-\fITEST\-ENTRY\fR := \fIsetname\fR [ { \fBbefore\fR | \fBafter\fR } \fIsetname\fR ]
-.PP
-Optional \fBcreate\fR options:
-.TP
-\fBsize\fR \fIvalue\fR
-The size of the list, the default is 8.
-.PP
-By the \fBipset\fR commad you can add, delete and test set names in a
-\fBlist:set\fR type of set.
-.PP
-By the \fBset\fR match or \fBSET\fR target of netfilter
-you can test, add or delete entries in the sets added to the \fBlist:set\fR
-type of set. The match will try to find a matching entry in the sets and
-the target will try to add an entry to the first set to which it can be added.
-The number of direction options of the match and target are important: sets which
-require more parameters than specified are skipped, while sets with equal
-or less parameters are checked, elements added/deleted. For example if \fIa\fR and
-\fIb\fR are \fBlist:set\fR type of sets then in the command
-.IP
-iptables \-m set \-\-match\-set a src,dst \-j SET \-\-add\-set b src,dst
-.PP
-the match and target will skip any set in \fIa\fR and \fIb\fR
-which stores data triples, but will match all sets with single or double
-data storage in \fIa\fR set and stop matching at the first successful set,
-and add src to the first single or src,dst to the first double data storage set
-in \fIb\fR to which the entry can be added. You can imagine a \fBlist:set\fR
-type of set as an ordered union of the set elements.
-.PP
-Please note: by the \fBipset\fR commad you can add, delete and \fBtest\fR
-the setnames in a \fBlist:set\fR type of set, and \fBnot\fR the presence of
-a set's member (such as an IP address).
-.SH "GENERAL RESTRICTIONS"
-Zero valued set entries cannot be used with hash methods. Zero protocol value with ports
-cannot be used.
-.SH "COMMENTS"
-If you want to store same size subnets from a given network
-(say /24 blocks from a /8 network), use the \fBbitmap:ip\fR set type.
-If you want to store random same size networks (say random /24 blocks),
-use the \fBhash:ip\fR set type. If you have got random size of netblocks,
-use \fBhash:net\fR.
-.PP
-Backward compatibility is maintained and old \fBipset\fR syntax is still supported.
-.PP
-The \fBiptree\fR and \fBiptreemap\fR set types are removed: if you refer to them,
-they are automatically replaced by \fBhash:ip\fR type of sets.
-.SH "DIAGNOSTICS"
-Various error messages are printed to standard error. The exit code
-is 0 for correct functioning.
-.SH "BUGS"
-Bugs? No, just funny features. :\-)
-OK, just kidding...
-.SH "SEE ALSO"
-\fBiptables\fR(8),
-\fBip6tables\fR(8)
-.SH "AUTHORS"
-Jozsef Kadlecsik wrote ipset, which is based on ippool by
-Joakim Axelsson, Patrick Schaaf and Martin Josefsson.
-.br
-Sven Wegener wrote the iptreemap type.
-.SH "LAST REMARK"
-\fBI stand on the shoulders of giants.\fR
+++ /dev/null
-/* Copyright 2000-2002 Joakim Axelsson (gozem@linux.nu)
- * Patrick Schaaf (bof@bof.de)
- * Copyright 2003-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <ctype.h> /* isspace */
-#include <stdarg.h> /* va_* */
-#include <stdbool.h> /* bool */
-#include <stdio.h> /* fprintf, fgets */
-#include <stdlib.h> /* exit */
-#include <string.h> /* str* */
-
-#include <config.h>
-
-#include <libipset/debug.h> /* D() */
-#include <libipset/data.h> /* enum ipset_data */
-#include <libipset/parse.h> /* ipset_parse_* */
-#include <libipset/session.h> /* ipset_session_* */
-#include <libipset/types.h> /* struct ipset_type */
-#include <libipset/ui.h> /* core options, commands */
-#include <libipset/utils.h> /* STREQ */
-
-static char program_name[] = "ipset";
-static char program_version[] = "6.10-genl-xta";
-
-static struct ipset_session *session;
-static uint32_t restore_line;
-static bool interactive;
-static char cmdline[1024];
-static char *newargv[255];
-static int newargc;
-
-/* The known set types: (typename, revision, family) is unique */
-extern struct ipset_type ipset_bitmap_ip0;
-extern struct ipset_type ipset_bitmap_ipmac0;
-extern struct ipset_type ipset_bitmap_port0;
-extern struct ipset_type ipset_hash_ip0;
-extern struct ipset_type ipset_hash_net0;
-extern struct ipset_type ipset_hash_net1;
-extern struct ipset_type ipset_hash_netport1;
-extern struct ipset_type ipset_hash_netport2;
-extern struct ipset_type ipset_hash_netiface0;
-extern struct ipset_type ipset_hash_ipport1;
-extern struct ipset_type ipset_hash_ipportip1;
-extern struct ipset_type ipset_hash_ipportnet1;
-extern struct ipset_type ipset_hash_ipportnet2;
-extern struct ipset_type ipset_list_set0;
-
-enum exittype {
- NO_PROBLEM = 0,
- OTHER_PROBLEM,
- PARAMETER_PROBLEM,
- VERSION_PROBLEM,
- SESSION_PROBLEM,
-};
-
-static int __attribute__((format(printf, 2, 3)))
-exit_error(int status, const char *msg, ...)
-{
- bool quiet = !interactive &&
- session &&
- ipset_envopt_test(session, IPSET_ENV_QUIET);
-
- if (status && msg && !quiet) {
- va_list args;
-
- fprintf(stderr, "%s v%s: ", program_name, program_version);
- va_start(args, msg);
- vfprintf(stderr, msg, args);
- va_end(args);
- if (status != SESSION_PROBLEM)
- fprintf(stderr, "\n");
-
- if (status == PARAMETER_PROBLEM)
- fprintf(stderr,
- "Try `%s help' for more information.\n",
- program_name);
- }
- /* Ignore errors in interactive mode */
- if (status && interactive) {
- if (session)
- ipset_session_report_reset(session);
- return -1;
- }
-
- if (session)
- ipset_session_fini(session);
-
- D("status: %u", status);
- exit(status > VERSION_PROBLEM ? OTHER_PROBLEM : status);
- /* Unreached */
- return -1;
-}
-
-static int
-handle_error(void)
-{
- if (ipset_session_warning(session) &&
- !ipset_envopt_test(session, IPSET_ENV_QUIET))
- fprintf(stderr, "Warning: %s\n",
- ipset_session_warning(session));
- if (ipset_session_error(session))
- return exit_error(SESSION_PROBLEM, "%s",
- ipset_session_error(session));
-
- if (!interactive) {
- ipset_session_fini(session);
- exit(OTHER_PROBLEM);
- }
-
- ipset_session_report_reset(session);
- return -1;
-}
-
-static void
-help(void)
-{
- const struct ipset_commands *c;
- const struct ipset_envopts *opt = ipset_envopts;
-
- printf("%s v%s\n\n"
- "Usage: %s [options] COMMAND\n\nCommands:\n",
- program_name, program_version, program_name);
-
- for (c = ipset_commands; c->cmd; c++)
- printf("%s %s\n", c->name[0], c->help);
- printf("\nOptions:\n");
-
- while (opt->flag) {
- if (opt->help)
- printf("%s %s\n", opt->name[0], opt->help);
- opt++;
- }
-}
-
-/* Build faked argv from parsed line */
-static void
-build_argv(char *buffer)
-{
- char *ptr;
- int i;
-
- /* Reset */
- for (i = 1; i < newargc; i++)
- newargv[i] = NULL;
- newargc = 1;
-
- ptr = strtok(buffer, " \t\r\n");
- newargv[newargc++] = ptr;
- while ((ptr = strtok(NULL, " \t\r\n")) != NULL) {
- if ((newargc + 1) < (int)(sizeof(newargv)/sizeof(char *)))
- newargv[newargc++] = ptr;
- else {
- exit_error(PARAMETER_PROBLEM,
- "Line is too long to parse.");
- return;
- }
- }
-}
-
-/* Main parser function, workhorse */
-int parse_commandline(int argc, char *argv[]);
-
-/*
- * Performs a restore from stdin
- */
-static int
-restore(char *argv0)
-{
- int ret = 0;
- char *c;
-
- /* Initialize newargv/newargc */
- newargc = 0;
- newargv[newargc++] = argv0;
-
- while (fgets(cmdline, sizeof(cmdline), stdin)) {
- restore_line++;
- c = cmdline;
- while (isspace(c[0]))
- c++;
- if (c[0] == '\0' || c[0] == '#')
- continue;
- else if (STREQ(c, "COMMIT\n") || STREQ(c, "COMMIT\r\n")) {
- ret = ipset_commit(session);
- if (ret < 0)
- handle_error();
- continue;
- }
- /* Build faked argv, argc */
- build_argv(c);
-
- /* Execute line */
- ret = parse_commandline(newargc, newargv);
- if (ret < 0)
- handle_error();
- }
- /* implicit "COMMIT" at EOF */
- ret = ipset_commit(session);
- if (ret < 0)
- handle_error();
-
- return ret;
-}
-
-static int
-call_parser(int *argc, char *argv[], const struct ipset_arg *args)
-{
- int ret = 0;
- const struct ipset_arg *arg;
- const char *optstr;
-
- /* Currently CREATE and ADT may have got additional arguments */
- 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[1];
- /* Shift off matched option */
- D("match %s", arg->name[0]);
- ipset_shift_argv(argc, argv, 1);
- switch (arg->has_arg) {
- case IPSET_MANDATORY_ARG:
- if (*argc < 2)
- return exit_error(PARAMETER_PROBLEM,
- "Missing mandatory argument "
- "of option `%s'",
- arg->name[0]);
- /* Fall through */
- case IPSET_OPTIONAL_ARG:
- if (*argc >= 2) {
- ret = ipset_call_parser(session,
- arg, argv[1]);
- if (ret < 0)
- return ret;
- ipset_shift_argv(argc, argv, 1);
- break;
- }
- /* Fall through */
- default:
- ret = ipset_call_parser(session, arg, optstr);
- if (ret < 0)
- return ret;
- }
- break;
- }
- if (!arg->opt)
- goto err_unknown;
- }
- return ret;
-
-err_unknown:
- return exit_error(PARAMETER_PROBLEM, "Unknown argument: `%s'", argv[1]);
-}
-
-static enum ipset_adt
-cmd2cmd(int cmd)
-{
- switch (cmd) {
- case IPSET_CMD_ADD:
- return IPSET_ADD;
- case IPSET_CMD_DEL:
- return IPSET_DEL;
- case IPSET_CMD_TEST:
- return IPSET_TEST;
- case IPSET_CMD_CREATE:
- return IPSET_CREATE;
- default:
- return 0;
- }
-}
-
-static void
-check_mandatory(const struct ipset_type *type, enum ipset_cmd command)
-{
- enum ipset_adt cmd = cmd2cmd(command);
- uint64_t flags = ipset_data_flags(ipset_session_data(session));
- uint64_t mandatory = type->mandatory[cmd];
- const struct ipset_arg *arg = type->args[cmd];
-
- /* Range can be expressed by ip/cidr */
- if (flags & IPSET_FLAG(IPSET_OPT_CIDR))
- flags |= IPSET_FLAG(IPSET_OPT_IP_TO);
-
- mandatory &= ~flags;
- if (!mandatory)
- return;
- if (!arg) {
- exit_error(OTHER_PROBLEM,
- "There are missing mandatory flags "
- "but can't check them. "
- "It's a bug, please report the problem.");
- return;
- }
-
- for (; arg->opt; arg++)
- if (mandatory & IPSET_FLAG(arg->opt)) {
- exit_error(PARAMETER_PROBLEM,
- "Mandatory option `%s' is missing",
- arg->name[0]);
- return;
- }
-}
-
-static const char *
-cmd2name(enum ipset_cmd cmd)
-{
- const struct ipset_commands *c;
-
- for (c = ipset_commands; c->cmd; c++)
- if (cmd == c->cmd)
- return c->name[0];
- return "unknown command";
-}
-
-static const char *
-session_family(void)
-{
- switch (ipset_data_family(ipset_session_data(session))) {
- case NFPROTO_IPV4:
- return "inet";
- case NFPROTO_IPV6:
- return "inet6";
- default:
- return "unspec";
- }
-}
-
-static void
-check_allowed(const struct ipset_type *type, enum ipset_cmd command)
-{
- uint64_t flags = ipset_data_flags(ipset_session_data(session));
- enum ipset_adt cmd = cmd2cmd(command);
- uint64_t allowed = type->full[cmd];
- uint64_t cmdflags = command == IPSET_CMD_CREATE
- ? IPSET_CREATE_FLAGS : IPSET_ADT_FLAGS;
- const struct ipset_arg *arg = type->args[cmd];
- enum ipset_opt i;
-
- /* Range can be expressed by ip/cidr or from-to */
- if (allowed & IPSET_FLAG(IPSET_OPT_IP_TO))
- allowed |= IPSET_FLAG(IPSET_OPT_CIDR);
-
- for (i = IPSET_OPT_IP; i < IPSET_OPT_FLAGS; i++) {
- if (!(cmdflags & IPSET_FLAG(i)) ||
- (allowed & IPSET_FLAG(i)) ||
- !(flags & IPSET_FLAG(i)))
- continue;
- /* Not allowed element-expressions */
- switch (i) {
- case IPSET_OPT_CIDR:
- exit_error(OTHER_PROBLEM,
- "IP/CIDR range is not allowed in command %s "
- "with set type %s and family %s",
- cmd2name(command), type->name,
- session_family());
- return;
- case IPSET_OPT_IP_TO:
- exit_error(OTHER_PROBLEM,
- "FROM-TO IP range is not allowed in command %s "
- "with set type %s and family %s",
- cmd2name(command), type->name,
- session_family());
- return;
- case IPSET_OPT_PORT_TO:
- exit_error(OTHER_PROBLEM,
- "FROM-TO port range is not allowed in command %s "
- "with set type %s and family %s",
- cmd2name(command), type->name,
- session_family());
- return;
- default:
- break;
- }
- /* Other options */
- if (!arg) {
- exit_error(OTHER_PROBLEM,
- "There are not allowed options (%u) "
- "but option list is NULL. "
- "It's a bug, please report the problem.", i);
- return;
- }
- for (; arg->opt; arg++) {
- if (arg->opt != i)
- continue;
- exit_error(OTHER_PROBLEM,
- "%s parameter is not allowed in command %s "
- "with set type %s and family %s",
- arg->name[0],
- cmd2name(command), type->name,
- session_family());
- return;
- }
- exit_error(OTHER_PROBLEM,
- "There are not allowed options (%u) "
- "but can't resolve them. "
- "It's a bug, please report the problem.", i);
- return;
- }
-}
-
-static const struct ipset_type *
-type_find(const char *name)
-{
- const struct ipset_type *t = ipset_types();
-
- while (t) {
- if (ipset_match_typename(name, t))
- return t;
- t = t->next;
- }
- return NULL;
-}
-
-/* Workhorse */
-int
-parse_commandline(int argc, char *argv[])
-{
- int ret = 0;
- enum ipset_cmd cmd = IPSET_CMD_NONE;
- int i;
- char *arg0 = NULL, *arg1 = NULL, *c;
- const struct ipset_envopts *opt;
- const struct ipset_commands *command;
- const struct ipset_type *type;
-
- /* Set session lineno to report parser errors correctly */
- ipset_session_lineno(session, restore_line);
-
- /* Commandline parsing, somewhat similar to that of 'ip' */
-
- /* First: parse core options */
- for (opt = ipset_envopts; opt->flag; opt++) {
- for (i = 1; i < argc; ) {
- if (!ipset_match_envopt(argv[i], opt->name)) {
- i++;
- continue;
- }
- /* Shift off matched option */
- ipset_shift_argv(&argc, argv, i);
- switch (opt->has_arg) {
- case IPSET_MANDATORY_ARG:
- if (i + 1 > argc)
- return exit_error(PARAMETER_PROBLEM,
- "Missing mandatory argument "
- "to option %s",
- opt->name[0]);
- /* Fall through */
- case IPSET_OPTIONAL_ARG:
- if (i + 1 <= argc) {
- ret = opt->parse(session, opt->flag,
- argv[i]);
- if (ret < 0)
- return handle_error();
- ipset_shift_argv(&argc, argv, i);
- }
- break;
- case IPSET_NO_ARG:
- ret = opt->parse(session, opt->flag,
- opt->name[0]);
- if (ret < 0)
- return handle_error();
- break;
- default:
- break;
- }
- }
- }
-
- /* Second: parse command */
- for (command = ipset_commands;
- argc > 1 && command->cmd && cmd == IPSET_CMD_NONE;
- command++) {
- if (!ipset_match_cmd(argv[1], command->name))
- 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;
- }
-
- /* 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 */
- switch (cmd) {
- case IPSET_CMD_NONE:
- if (interactive) {
- printf("No command specified\n");
- return 0;
- }
- if (argc > 1 && STREQ(argv[1], "-")) {
- interactive = true;
- printf("%s> ", program_name);
- /* Initialize newargv/newargc */
- newargv[newargc++] = program_name;
- while (fgets(cmdline, sizeof(cmdline), stdin)) {
- c = cmdline;
- while (isspace(c[0]))
- c++;
- if (c[0] == '\0' || c[0] == '#')
- continue;
- /* Build fake argv, argc */
- build_argv(c);
- /* Execute line: ignore errors */
- parse_commandline(newargc, newargv);
- printf("%s> ", program_name);
- }
- return exit_error(NO_PROBLEM, NULL);
- }
- if (argc > 1)
- return exit_error(PARAMETER_PROBLEM,
- "No command specified: unknown argument %s",
- argv[1]);
- return exit_error(PARAMETER_PROBLEM, "No command specified.");
- case IPSET_CMD_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);
- case IPSET_CMD_HELP:
- help();
-
- if (interactive ||
- !ipset_envopt_test(session, IPSET_ENV_QUIET)) {
- if (arg0) {
- /* Type-specific help, without kernel checking */
- type = type_find(arg0);
- if (!type)
- return exit_error(PARAMETER_PROBLEM,
- "Unknown settype: `%s'", arg0);
- printf("\n%s type specific options:\n\n%s",
- type->name, type->usage);
- if (type->usagefn)
- type->usagefn();
- if (type->family == NFPROTO_UNSPEC)
- printf("\nType %s is family neutral.\n",
- type->name);
- else if (type->family == NFPROTO_IPSET_IPV46)
- printf("\nType %s supports INET "
- "and INET6.\n",
- type->name);
- else
- printf("\nType %s supports family "
- "%s only.\n",
- type->name,
- type->family == NFPROTO_IPV4
- ? "INET" : "INET6");
- } else {
- printf("\nSupported set types:\n");
- type = ipset_types();
- while (type) {
- printf(" %s\n", type->name);
- type = type->next;
- }
- }
- }
- if (interactive)
- return 0;
- return exit_error(NO_PROBLEM, NULL);
- case IPSET_CMD_QUIT:
- return exit_error(NO_PROBLEM, NULL);
- default:
- break;
- }
-
- /* Forth: parse command args and issue the command */
- switch (cmd) {
- case IPSET_CMD_CREATE:
- /* Args: setname typename [type specific options] */
- ret = ipset_parse_setname(session, IPSET_SETNAME, arg0);
- if (ret < 0)
- return handle_error();
-
- ret = ipset_parse_typename(session, IPSET_OPT_TYPENAME, arg1);
- if (ret < 0)
- return handle_error();
-
- type = ipset_type_get(session, cmd);
- if (type == NULL)
- return handle_error();
-
- /* Parse create options */
- ret = call_parser(&argc, argv, type->args[IPSET_CREATE]);
- if (ret < 0)
- return handle_error();
- else if (ret)
- return ret;
-
- /* Check mandatory, then allowed options */
- check_mandatory(type, cmd);
- check_allowed(type, cmd);
-
- break;
- case IPSET_CMD_DESTROY:
- case IPSET_CMD_FLUSH:
- case IPSET_CMD_LIST:
- case IPSET_CMD_SAVE:
- /* Args: [setname] */
- if (arg0) {
- ret = ipset_parse_setname(session,
- IPSET_SETNAME, arg0);
- if (ret < 0)
- return handle_error();
- }
- break;
-
- case IPSET_CMD_RENAME:
- case IPSET_CMD_SWAP:
- /* Args: from-setname to-setname */
- ret = ipset_parse_setname(session, IPSET_SETNAME, arg0);
- if (ret < 0)
- return handle_error();
- ret = ipset_parse_setname(session, IPSET_OPT_SETNAME2, arg1);
- if (ret < 0)
- return handle_error();
- break;
-
- case IPSET_CMD_RESTORE:
- /* Restore mode */
- if (argc > 1)
- return exit_error(PARAMETER_PROBLEM,
- "Unknown argument %s", argv[1]);
- return restore(argv[0]);
- case IPSET_CMD_ADD:
- case IPSET_CMD_DEL:
- case IPSET_CMD_TEST:
- D("ADT: setname %s", arg0);
- /* Args: setname ip [options] */
- ret = ipset_parse_setname(session, IPSET_SETNAME, arg0);
- if (ret < 0)
- return handle_error();
-
- type = ipset_type_get(session, cmd);
- if (type == NULL)
- return handle_error();
-
- ret = ipset_parse_elem(session, type->last_elem_optional, arg1);
- if (ret < 0)
- return handle_error();
-
- /* Parse additional ADT options */
- ret = call_parser(&argc, argv, type->args[cmd2cmd(cmd)]);
- if (ret < 0)
- return handle_error();
- else if (ret)
- return ret;
-
- /* Check mandatory, then allowed options */
- check_mandatory(type, cmd);
- check_allowed(type, cmd);
-
- break;
- default:
- break;
- }
-
- if (argc > 1)
- return exit_error(PARAMETER_PROBLEM,
- "Unknown argument %s", argv[1]);
- ret = ipset_cmd(session, cmd, restore_line);
- D("ret %d", ret);
- /* Special case for TEST and non-quiet mode */
- if (cmd == IPSET_CMD_TEST && ipset_session_warning(session)) {
- if (!ipset_envopt_test(session, IPSET_ENV_QUIET))
- fprintf(stderr, "%s", ipset_session_warning(session));
- ipset_session_report_reset(session);
- }
- if (ret < 0)
- handle_error();
-
- return ret;
-}
-
-int
-main(int argc, char *argv[])
-{
- int ret;
-
- /* Register types */
- ipset_type_add(&ipset_bitmap_ip0);
- ipset_type_add(&ipset_bitmap_ipmac0);
- ipset_type_add(&ipset_bitmap_port0);
- ipset_type_add(&ipset_hash_ip0);
- ipset_type_add(&ipset_hash_net0);
- ipset_type_add(&ipset_hash_net1);
- ipset_type_add(&ipset_hash_netport1);
- ipset_type_add(&ipset_hash_netport2);
- ipset_type_add(&ipset_hash_netiface0);
- ipset_type_add(&ipset_hash_ipport1);
- ipset_type_add(&ipset_hash_ipportip1);
- ipset_type_add(&ipset_hash_ipportnet1);
- ipset_type_add(&ipset_hash_ipportnet2);
- ipset_type_add(&ipset_list_set0);
-
- /* Initialize session */
- session = ipset_session_init(printf);
- if (session == NULL)
- return exit_error(OTHER_PROBLEM,
- "Cannot initialize ipset session, aborting.");
-
- ret = parse_commandline(argc, argv);
-
- ipset_session_fini(session);
-
- return ret;
-}
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <libipset/data.h> /* IPSET_OPT_* */
-#include <libipset/parse.h> /* parser functions */
-#include <libipset/print.h> /* printing functions */
-#include <libipset/types.h> /* prototypes */
-
-/* Parse commandline arguments */
-static const struct ipset_arg bitmap_ip_create_args[] = {
- { .name = { "range", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP,
- .parse = ipset_parse_netrange, .print = ipset_print_ip,
- },
- { .name = { "netmask", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_NETMASK,
- .parse = ipset_parse_netmask, .print = ipset_print_number,
- },
- { .name = { "timeout", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- /* Backward compatibility */
- { .name = { "from", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP,
- .parse = ipset_parse_single_ip,
- },
- { .name = { "to", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP_TO,
- .parse = ipset_parse_single_ip,
- },
- { .name = { "network", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP,
- .parse = ipset_parse_net,
- },
- { },
-};
-
-static const struct ipset_arg bitmap_ip_add_args[] = {
- { .name = { "timeout", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- { },
-};
-
-static const char bitmap_ip_usage[] =
-"create SETNAME bitmap:ip range IP/CIDR|FROM-TO\n"
-" [netmask CIDR] [timeout VALUE]\n"
-"add SETNAME IP|IP/CIDR|FROM-TO [timeout VALUE]\n"
-"del SETNAME IP|IP/CIDR|FROM-TO\n"
-"test SETNAME IP\n\n"
-"where IP, FROM and TO are IPv4 addresses (or hostnames),\n"
-" CIDR is a valid IPv4 CIDR prefix.\n";
-
-struct ipset_type ipset_bitmap_ip0 = {
- .name = "bitmap:ip",
- .alias = { "ipmap", NULL },
- .revision = 0,
- .family = NFPROTO_IPV4,
- .dimension = IPSET_DIM_ONE,
- .elem = {
- [IPSET_DIM_ONE - 1] = {
- .parse = ipset_parse_ip,
- .print = ipset_print_ip,
- .opt = IPSET_OPT_IP
- },
- },
- .args = {
- [IPSET_CREATE] = bitmap_ip_create_args,
- [IPSET_ADD] = bitmap_ip_add_args,
- },
- .mandatory = {
- [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_IP_TO),
- [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP),
- [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP),
- [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP),
- },
- .full = {
- [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_IP_TO)
- | IPSET_FLAG(IPSET_OPT_NETMASK)
- | IPSET_FLAG(IPSET_OPT_TIMEOUT),
- [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_IP_TO)
- | IPSET_FLAG(IPSET_OPT_TIMEOUT),
- [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_IP_TO),
- [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP),
- },
-
- .usage = bitmap_ip_usage,
-};
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <libipset/data.h> /* IPSET_OPT_* */
-#include <libipset/parse.h> /* parser functions */
-#include <libipset/print.h> /* printing functions */
-#include <libipset/types.h> /* prototypes */
-
-/* Parse commandline arguments */
-static const struct ipset_arg bitmap_ipmac_create_args[] = {
- { .name = { "range", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP,
- .parse = ipset_parse_netrange, .print = ipset_print_ip,
- },
- { .name = { "timeout", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- /* Backward compatibility */
- { .name = { "from", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP,
- .parse = ipset_parse_single_ip,
- },
- { .name = { "to", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP_TO,
- .parse = ipset_parse_single_ip,
- },
- { .name = { "network", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP,
- .parse = ipset_parse_net,
- },
- { },
-};
-
-static const struct ipset_arg bitmap_ipmac_add_args[] = {
- { .name = { "timeout", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- { },
-};
-
-static const char bitmap_ipmac_usage[] =
-"create SETNAME bitmap:ip,mac range IP/CIDR|FROM-TO\n"
-" [matchunset] [timeout VALUE]\n"
-"add SETNAME IP[,MAC] [timeout VALUE]\n"
-"del SETNAME IP[,MAC]\n"
-"test SETNAME IP[,MAC]\n\n"
-"where IP, FROM and TO are IPv4 addresses (or hostnames),\n"
-" CIDR is a valid IPv4 CIDR prefix,\n"
-" MAC is a valid MAC address.\n";
-
-struct ipset_type ipset_bitmap_ipmac0 = {
- .name = "bitmap:ip,mac",
- .alias = { "macipmap", NULL },
- .revision = 0,
- .family = NFPROTO_IPV4,
- .dimension = IPSET_DIM_TWO,
- .last_elem_optional = true,
- .elem = {
- [IPSET_DIM_ONE - 1] = {
- .parse = ipset_parse_single_ip,
- .print = ipset_print_ip,
- .opt = IPSET_OPT_IP
- },
- [IPSET_DIM_TWO - 1] = {
- .parse = ipset_parse_ether,
- .print = ipset_print_ether,
- .opt = IPSET_OPT_ETHER
- },
- },
- .args = {
- [IPSET_CREATE] = bitmap_ipmac_create_args,
- [IPSET_ADD] = bitmap_ipmac_add_args,
- },
- .mandatory = {
- [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_IP_TO),
- [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP),
- [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP),
- [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP),
- },
- .full = {
- [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_IP_TO)
- | IPSET_FLAG(IPSET_OPT_TIMEOUT),
- [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_ETHER)
- | IPSET_FLAG(IPSET_OPT_TIMEOUT),
- [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_ETHER),
- [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_ETHER),
- },
-
- .usage = bitmap_ipmac_usage,
-};
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <libipset/data.h> /* IPSET_OPT_* */
-#include <libipset/parse.h> /* parser functions */
-#include <libipset/print.h> /* printing functions */
-#include <libipset/types.h> /* prototypes */
-
-/* Parse commandline arguments */
-static const struct ipset_arg bitmap_port_create_args[] = {
- { .name = { "range", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_PORT,
- .parse = ipset_parse_tcp_port, .print = ipset_print_port,
- },
- { .name = { "timeout", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- /* Backward compatibility */
- { .name = { "from", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_PORT,
- .parse = ipset_parse_single_tcp_port,
- },
- { .name = { "to", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_PORT_TO,
- .parse = ipset_parse_single_tcp_port,
- },
- { },
-};
-
-static const struct ipset_arg bitmap_port_add_args[] = {
- { .name = { "timeout", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- { },
-};
-
-static const char bitmap_port_usage[] =
-"create SETNAME bitmap:port range FROM-TO\n"
-" [timeout VALUE]\n"
-"add SETNAME PORT|FROM-TO [timeout VALUE]\n"
-"del SETNAME PORT|FROM-TO\n"
-"test SETNAME PORT\n\n"
-"where PORT, FROM and TO are port numbers or port names from /etc/services.\n";
-
-struct ipset_type ipset_bitmap_port0 = {
- .name = "bitmap:port",
- .alias = { "portmap", NULL },
- .revision = 0,
- .family = NFPROTO_UNSPEC,
- .dimension = IPSET_DIM_ONE,
- .elem = {
- [IPSET_DIM_ONE - 1] = {
- .parse = ipset_parse_tcp_port,
- .print = ipset_print_port,
- .opt = IPSET_OPT_PORT
- },
- },
- .args = {
- [IPSET_CREATE] = bitmap_port_create_args,
- [IPSET_ADD] = bitmap_port_add_args,
- },
- .mandatory = {
- [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_PORT)
- | IPSET_FLAG(IPSET_OPT_PORT_TO),
- [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_PORT),
- [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_PORT),
- [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_PORT),
- },
- .full = {
- [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_PORT)
- | IPSET_FLAG(IPSET_OPT_PORT_TO)
- | IPSET_FLAG(IPSET_OPT_TIMEOUT),
- [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_PORT)
- | IPSET_FLAG(IPSET_OPT_PORT_TO)
- | IPSET_FLAG(IPSET_OPT_TIMEOUT),
- [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_PORT)
- | IPSET_FLAG(IPSET_OPT_PORT_TO),
- [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_PORT),
- },
-
- .usage = bitmap_port_usage,
-};
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <libipset/data.h> /* IPSET_OPT_* */
-#include <libipset/parse.h> /* parser functions */
-#include <libipset/print.h> /* printing functions */
-#include <libipset/types.h> /* prototypes */
-
-/* Parse commandline arguments */
-static const struct ipset_arg hash_ip_create_args[] = {
- { .name = { "family", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_FAMILY,
- .parse = ipset_parse_family, .print = ipset_print_family,
- },
- /* Alias: family inet */
- { .name = { "-4", NULL },
- .has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY,
- .parse = ipset_parse_family,
- },
- /* Alias: family inet6 */
- { .name = { "-6", NULL },
- .has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY,
- .parse = ipset_parse_family,
- },
- { .name = { "hashsize", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_HASHSIZE,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- { .name = { "maxelem", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_MAXELEM,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- { .name = { "netmask", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_NETMASK,
- .parse = ipset_parse_netmask, .print = ipset_print_number,
- },
- { .name = { "timeout", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- /* Ignored options: backward compatibilty */
- { .name = { "probes", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_PROBES,
- .parse = ipset_parse_ignored, .print = ipset_print_number,
- },
- { .name = { "resize", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_RESIZE,
- .parse = ipset_parse_ignored, .print = ipset_print_number,
- },
- { .name = { "gc", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_GC,
- .parse = ipset_parse_ignored, .print = ipset_print_number,
- },
- { },
-};
-
-static const struct ipset_arg hash_ip_add_args[] = {
- { .name = { "timeout", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- { },
-};
-
-static const char hash_ip_usage[] =
-"create SETNAME hash:ip\n"
-" [family inet|inet6]\n"
-" [hashsize VALUE] [maxelem VALUE]\n"
-" [netmask CIDR] [timeout VALUE]\n"
-"add SETNAME IP [timeout VALUE]\n"
-"del SETNAME IP\n"
-"test SETNAME IP\n\n"
-"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 in IP/CIDR or FROM-TO form\n"
-" is supported for IPv4.\n";
-
-struct ipset_type ipset_hash_ip0 = {
- .name = "hash:ip",
- .alias = { "iphash", NULL },
- .revision = 0,
- .family = NFPROTO_IPSET_IPV46,
- .dimension = IPSET_DIM_ONE,
- .elem = {
- [IPSET_DIM_ONE - 1] = {
- .parse = ipset_parse_ip4_single6,
- .print = ipset_print_ip,
- .opt = IPSET_OPT_IP
- },
- },
- .args = {
- [IPSET_CREATE] = hash_ip_create_args,
- [IPSET_ADD] = hash_ip_add_args,
- },
- .mandatory = {
- [IPSET_CREATE] = 0,
- [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP),
- [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP),
- [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP),
- },
- .full = {
- [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE)
- | IPSET_FLAG(IPSET_OPT_MAXELEM)
- | IPSET_FLAG(IPSET_OPT_NETMASK)
- | IPSET_FLAG(IPSET_OPT_TIMEOUT),
- [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_IP_TO)
- | IPSET_FLAG(IPSET_OPT_TIMEOUT),
- [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_IP_TO),
- [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP),
- },
-
- .usage = hash_ip_usage,
-};
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <libipset/data.h> /* IPSET_OPT_* */
-#include <libipset/parse.h> /* parser functions */
-#include <libipset/print.h> /* printing functions */
-#include <libipset/ui.h> /* ipset_port_usage */
-#include <libipset/types.h> /* prototypes */
-
-/* Parse commandline arguments */
-static const struct ipset_arg hash_ipport_create_args[] = {
- { .name = { "family", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_FAMILY,
- .parse = ipset_parse_family, .print = ipset_print_family,
- },
- /* Alias: family inet */
- { .name = { "-4", NULL },
- .has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY,
- .parse = ipset_parse_family,
- },
- /* Alias: family inet6 */
- { .name = { "-6", NULL },
- .has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY,
- .parse = ipset_parse_family,
- },
- { .name = { "hashsize", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_HASHSIZE,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- { .name = { "maxelem", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_MAXELEM,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- { .name = { "timeout", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- /* Backward compatibility */
- { .name = { "probes", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_PROBES,
- .parse = ipset_parse_ignored, .print = ipset_print_number,
- },
- { .name = { "resize", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_RESIZE,
- .parse = ipset_parse_ignored, .print = ipset_print_number,
- },
- { .name = { "from", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP,
- .parse = ipset_parse_ignored,
- },
- { .name = { "to", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP_TO,
- .parse = ipset_parse_ignored,
- },
- { .name = { "network", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP,
- .parse = ipset_parse_ignored,
- },
- { },
-};
-
-static const struct ipset_arg hash_ipport_add_args[] = {
- { .name = { "timeout", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- { },
-};
-
-static const char hash_ipport1_usage[] =
-"create SETNAME hash:ip,port\n"
-" [family inet|inet6]\n"
-" [hashsize VALUE] [maxelem VALUE]\n"
-" [timeout VALUE]\n"
-"add SETNAME IP,PROTO:PORT [timeout VALUE]\n"
-"del SETNAME IP,PROTO:PORT\n"
-"test SETNAME IP,PROTO:PORT\n\n"
-"where depending on the INET family\n"
-" 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/SCTP/UDP/UDPLITE\n"
-" port range is supported both for IPv4 and IPv6.\n";
-
-struct ipset_type ipset_hash_ipport1 = {
- .name = "hash:ip,port",
- .alias = { "ipporthash", NULL },
- .revision = 1,
- .family = NFPROTO_IPSET_IPV46,
- .dimension = IPSET_DIM_TWO,
- .elem = {
- [IPSET_DIM_ONE - 1] = {
- .parse = ipset_parse_ip4_single6,
- .print = ipset_print_ip,
- .opt = IPSET_OPT_IP
- },
- [IPSET_DIM_TWO - 1] = {
- .parse = ipset_parse_proto_port,
- .print = ipset_print_proto_port,
- .opt = IPSET_OPT_PORT
- },
- },
- .args = {
- [IPSET_CREATE] = hash_ipport_create_args,
- [IPSET_ADD] = hash_ipport_add_args,
- },
- .mandatory = {
- [IPSET_CREATE] = 0,
- [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_PROTO)
- | IPSET_FLAG(IPSET_OPT_PORT),
- [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_PROTO)
- | IPSET_FLAG(IPSET_OPT_PORT),
- [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_PROTO)
- | IPSET_FLAG(IPSET_OPT_PORT),
- },
- .full = {
- [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE)
- | IPSET_FLAG(IPSET_OPT_MAXELEM)
- | IPSET_FLAG(IPSET_OPT_TIMEOUT),
- [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_IP_TO)
- | IPSET_FLAG(IPSET_OPT_PORT)
- | IPSET_FLAG(IPSET_OPT_PORT_TO)
- | IPSET_FLAG(IPSET_OPT_PROTO)
- | IPSET_FLAG(IPSET_OPT_TIMEOUT),
- [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_IP_TO)
- | IPSET_FLAG(IPSET_OPT_PORT)
- | IPSET_FLAG(IPSET_OPT_PORT_TO)
- | IPSET_FLAG(IPSET_OPT_PROTO),
- [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_PORT)
- | IPSET_FLAG(IPSET_OPT_PROTO),
- },
-
- .usage = hash_ipport1_usage,
- .usagefn = ipset_port_usage,
-};
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <libipset/data.h> /* IPSET_OPT_* */
-#include <libipset/parse.h> /* parser functions */
-#include <libipset/print.h> /* printing functions */
-#include <libipset/ui.h> /* ipset_port_usage */
-#include <libipset/types.h> /* prototypes */
-
-/* Parse commandline arguments */
-static const struct ipset_arg hash_ipportip_create_args[] = {
- { .name = { "family", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_FAMILY,
- .parse = ipset_parse_family, .print = ipset_print_family,
- },
- /* Alias: family inet */
- { .name = { "-4", NULL },
- .has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY,
- .parse = ipset_parse_family,
- },
- /* Alias: family inet6 */
- { .name = { "-6", NULL },
- .has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY,
- .parse = ipset_parse_family,
- },
- { .name = { "hashsize", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_HASHSIZE,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- { .name = { "maxelem", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_MAXELEM,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- { .name = { "timeout", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- /* Backward compatibility */
- { .name = { "probes", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_PROBES,
- .parse = ipset_parse_ignored, .print = ipset_print_number,
- },
- { .name = { "resize", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_RESIZE,
- .parse = ipset_parse_ignored, .print = ipset_print_number,
- },
- { .name = { "from", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP,
- .parse = ipset_parse_ignored,
- },
- { .name = { "to", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP_TO,
- .parse = ipset_parse_ignored,
- },
- { .name = { "network", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP,
- .parse = ipset_parse_ignored,
- },
- { },
-};
-
-static const struct ipset_arg hash_ipportip_add_args[] = {
- { .name = { "timeout", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- { },
-};
-
-static const char hash_ipportip1_usage[] =
-"create SETNAME hash:ip,port,ip\n"
-" [family inet|inet6]\n"
-" [hashsize VALUE] [maxelem VALUE]\n"
-" [timeout VALUE]\n"
-"add SETNAME IP,PROTO:PORT,IP [timeout VALUE]\n"
-"del SETNAME IP,PROTO:PORT,IP\n"
-"test SETNAME IP,PROTO:PORT,IP\n\n"
-"where depending on the INET family\n"
-" 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/SCTP/UDP/UDPLITE\n"
-" port range is supported both for IPv4 and IPv6.\n";
-
-struct ipset_type ipset_hash_ipportip1 = {
- .name = "hash:ip,port,ip",
- .alias = { "ipportiphash", NULL },
- .revision = 1,
- .family = NFPROTO_IPSET_IPV46,
- .dimension = IPSET_DIM_THREE,
- .elem = {
- [IPSET_DIM_ONE - 1] = {
- .parse = ipset_parse_ip4_single6,
- .print = ipset_print_ip,
- .opt = IPSET_OPT_IP
- },
- [IPSET_DIM_TWO - 1] = {
- .parse = ipset_parse_proto_port,
- .print = ipset_print_proto_port,
- .opt = IPSET_OPT_PORT
- },
- [IPSET_DIM_THREE - 1] = {
- .parse = ipset_parse_single_ip,
- .print = ipset_print_ip,
- .opt = IPSET_OPT_IP2
- },
- },
- .args = {
- [IPSET_CREATE] = hash_ipportip_create_args,
- [IPSET_ADD] = hash_ipportip_add_args,
- },
- .mandatory = {
- [IPSET_CREATE] = 0,
- [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_PORT)
- | IPSET_FLAG(IPSET_OPT_PROTO)
- | IPSET_FLAG(IPSET_OPT_IP2),
- [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_PORT)
- | IPSET_FLAG(IPSET_OPT_PROTO)
- | IPSET_FLAG(IPSET_OPT_IP2),
- [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_PORT)
- | IPSET_FLAG(IPSET_OPT_PROTO)
- | IPSET_FLAG(IPSET_OPT_IP2),
- },
- .full = {
- [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE)
- | IPSET_FLAG(IPSET_OPT_MAXELEM)
- | IPSET_FLAG(IPSET_OPT_TIMEOUT),
- [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_IP_TO)
- | IPSET_FLAG(IPSET_OPT_PORT)
- | IPSET_FLAG(IPSET_OPT_PORT_TO)
- | IPSET_FLAG(IPSET_OPT_PROTO)
- | IPSET_FLAG(IPSET_OPT_IP2)
- | IPSET_FLAG(IPSET_OPT_TIMEOUT),
- [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_IP_TO)
- | IPSET_FLAG(IPSET_OPT_PORT)
- | IPSET_FLAG(IPSET_OPT_PORT_TO)
- | IPSET_FLAG(IPSET_OPT_PROTO)
- | IPSET_FLAG(IPSET_OPT_IP2),
- [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_PORT)
- | IPSET_FLAG(IPSET_OPT_PROTO)
- | IPSET_FLAG(IPSET_OPT_IP2),
- },
-
- .usage = hash_ipportip1_usage,
- .usagefn = ipset_port_usage,
-};
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <libipset/data.h> /* IPSET_OPT_* */
-#include <libipset/parse.h> /* parser functions */
-#include <libipset/print.h> /* printing functions */
-#include <libipset/ui.h> /* ipset_port_usage */
-#include <libipset/types.h> /* prototypes */
-
-/* Parse commandline arguments */
-static const struct ipset_arg hash_ipportnet_create_args[] = {
- { .name = { "family", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_FAMILY,
- .parse = ipset_parse_family, .print = ipset_print_family,
- },
- /* Alias: family inet */
- { .name = { "-4", NULL },
- .has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY,
- .parse = ipset_parse_family,
- },
- /* Alias: family inet6 */
- { .name = { "-6", NULL },
- .has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY,
- .parse = ipset_parse_family,
- },
- { .name = { "hashsize", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_HASHSIZE,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- { .name = { "maxelem", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_MAXELEM,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- { .name = { "timeout", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- /* Backward compatibility */
- { .name = { "probes", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_PROBES,
- .parse = ipset_parse_ignored, .print = ipset_print_number,
- },
- { .name = { "resize", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_RESIZE,
- .parse = ipset_parse_ignored, .print = ipset_print_number,
- },
- { .name = { "from", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP,
- .parse = ipset_parse_ignored,
- },
- { .name = { "to", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP_TO,
- .parse = ipset_parse_ignored,
- },
- { .name = { "network", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_IP,
- .parse = ipset_parse_ignored,
- },
- { },
-};
-
-static const struct ipset_arg hash_ipportnet_add_args[] = {
- { .name = { "timeout", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- { },
-};
-
-static const char hash_ipportnet1_usage[] =
-"create SETNAME hash:ip,port,net\n"
-" [family inet|inet6]\n"
-" [hashsize VALUE] [maxelem VALUE]\n"
-" [timeout VALUE]\n"
-"add SETNAME IP,PROTO:PORT,IP[/CIDR] [timeout VALUE]\n"
-"del SETNAME IP,PROTO:PORT,IP[/CIDR]\n"
-"test SETNAME IP,PROTO:PORT,IP[/CIDR]\n\n"
-"where depending on the INET family\n"
-" IP are valid IPv4 or IPv6 addresses (or hostnames),\n"
-" 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/SCTP/UDP/UDPLITE\n"
-" port range is supported both for IPv4 and IPv6.\n";
-
-struct ipset_type ipset_hash_ipportnet1 = {
- .name = "hash:ip,port,net",
- .alias = { "ipportnethash", NULL },
- .revision = 1,
- .family = NFPROTO_IPSET_IPV46,
- .dimension = IPSET_DIM_THREE,
- .elem = {
- [IPSET_DIM_ONE - 1] = {
- .parse = ipset_parse_ip4_single6,
- .print = ipset_print_ip,
- .opt = IPSET_OPT_IP
- },
- [IPSET_DIM_TWO - 1] = {
- .parse = ipset_parse_proto_port,
- .print = ipset_print_proto_port,
- .opt = IPSET_OPT_PORT
- },
- [IPSET_DIM_THREE - 1] = {
- .parse = ipset_parse_ipnet,
- .print = ipset_print_ip,
- .opt = IPSET_OPT_IP2
- },
- },
- .args = {
- [IPSET_CREATE] = hash_ipportnet_create_args,
- [IPSET_ADD] = hash_ipportnet_add_args,
- },
- .mandatory = {
- [IPSET_CREATE] = 0,
- [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_PORT)
- | IPSET_FLAG(IPSET_OPT_PROTO)
- | IPSET_FLAG(IPSET_OPT_IP2),
- [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_PORT)
- | IPSET_FLAG(IPSET_OPT_PROTO)
- | IPSET_FLAG(IPSET_OPT_IP2),
- [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_PORT)
- | IPSET_FLAG(IPSET_OPT_PROTO)
- | IPSET_FLAG(IPSET_OPT_IP2),
- },
- .full = {
- [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE)
- | IPSET_FLAG(IPSET_OPT_MAXELEM)
- | IPSET_FLAG(IPSET_OPT_TIMEOUT),
- [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_CIDR)
- | IPSET_FLAG(IPSET_OPT_IP_TO)
- | IPSET_FLAG(IPSET_OPT_PORT)
- | IPSET_FLAG(IPSET_OPT_PORT_TO)
- | IPSET_FLAG(IPSET_OPT_PROTO)
- | IPSET_FLAG(IPSET_OPT_IP2)
- | IPSET_FLAG(IPSET_OPT_CIDR2)
- | IPSET_FLAG(IPSET_OPT_TIMEOUT),
- [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_CIDR)
- | IPSET_FLAG(IPSET_OPT_IP_TO)
- | IPSET_FLAG(IPSET_OPT_PORT)
- | IPSET_FLAG(IPSET_OPT_PORT_TO)
- | IPSET_FLAG(IPSET_OPT_PROTO)
- | IPSET_FLAG(IPSET_OPT_IP2)
- | IPSET_FLAG(IPSET_OPT_CIDR2),
- [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_PORT)
- | IPSET_FLAG(IPSET_OPT_PROTO)
- | IPSET_FLAG(IPSET_OPT_IP2)
- | IPSET_FLAG(IPSET_OPT_CIDR2),
- },
-
- .usage = hash_ipportnet1_usage,
- .usagefn = ipset_port_usage,
-};
-
-static const char hash_ipportnet2_usage[] =
-"create SETNAME hash:ip,port,net\n"
-" [family inet|inet6]\n"
-" [hashsize VALUE] [maxelem VALUE]\n"
-" [timeout VALUE]\n"
-"add SETNAME IP,PROTO:PORT,IP[/CIDR] [timeout VALUE]\n"
-"del SETNAME IP,PROTO:PORT,IP[/CIDR]\n"
-"test SETNAME IP,PROTO:PORT,IP[/CIDR]\n\n"
-"where depending on the INET family\n"
-" IP are valid IPv4 or IPv6 addresses (or hostnames),\n"
-" CIDR is a valid IPv4 or IPv6 CIDR prefix.\n"
-" Adding/deleting multiple elements in IP/CIDR or FROM-TO form\n"
-" in both IP components are supported for IPv4.\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_ipportnet2 = {
- .name = "hash:ip,port,net",
- .alias = { "ipportnethash", NULL },
- .revision = 2,
- .family = NFPROTO_IPSET_IPV46,
- .dimension = IPSET_DIM_THREE,
- .elem = {
- [IPSET_DIM_ONE - 1] = {
- .parse = ipset_parse_ip4_single6,
- .print = ipset_print_ip,
- .opt = IPSET_OPT_IP
- },
- [IPSET_DIM_TWO - 1] = {
- .parse = ipset_parse_proto_port,
- .print = ipset_print_proto_port,
- .opt = IPSET_OPT_PORT
- },
- [IPSET_DIM_THREE - 1] = {
- .parse = ipset_parse_ip4_net6,
- .print = ipset_print_ip,
- .opt = IPSET_OPT_IP2
- },
- },
- .args = {
- [IPSET_CREATE] = hash_ipportnet_create_args,
- [IPSET_ADD] = hash_ipportnet_add_args,
- },
- .mandatory = {
- [IPSET_CREATE] = 0,
- [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_PORT)
- | IPSET_FLAG(IPSET_OPT_PROTO)
- | IPSET_FLAG(IPSET_OPT_IP2),
- [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_PORT)
- | IPSET_FLAG(IPSET_OPT_PROTO)
- | IPSET_FLAG(IPSET_OPT_IP2),
- [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_PORT)
- | IPSET_FLAG(IPSET_OPT_PROTO)
- | IPSET_FLAG(IPSET_OPT_IP2),
- },
- .full = {
- [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE)
- | IPSET_FLAG(IPSET_OPT_MAXELEM)
- | IPSET_FLAG(IPSET_OPT_TIMEOUT),
- [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_CIDR)
- | IPSET_FLAG(IPSET_OPT_IP_TO)
- | IPSET_FLAG(IPSET_OPT_PORT)
- | IPSET_FLAG(IPSET_OPT_PORT_TO)
- | IPSET_FLAG(IPSET_OPT_PROTO)
- | IPSET_FLAG(IPSET_OPT_IP2)
- | IPSET_FLAG(IPSET_OPT_CIDR2)
- | IPSET_FLAG(IPSET_OPT_IP2_TO)
- | IPSET_FLAG(IPSET_OPT_TIMEOUT),
- [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_CIDR)
- | IPSET_FLAG(IPSET_OPT_IP_TO)
- | IPSET_FLAG(IPSET_OPT_PORT)
- | IPSET_FLAG(IPSET_OPT_PORT_TO)
- | IPSET_FLAG(IPSET_OPT_PROTO)
- | IPSET_FLAG(IPSET_OPT_IP2)
- | IPSET_FLAG(IPSET_OPT_CIDR2)
- | IPSET_FLAG(IPSET_OPT_IP2_TO),
- [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_PORT)
- | IPSET_FLAG(IPSET_OPT_PROTO)
- | IPSET_FLAG(IPSET_OPT_IP2)
- | IPSET_FLAG(IPSET_OPT_CIDR2),
- },
-
- .usage = hash_ipportnet2_usage,
- .usagefn = ipset_port_usage,
-};
-
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <libipset/data.h> /* IPSET_OPT_* */
-#include <libipset/parse.h> /* parser functions */
-#include <libipset/print.h> /* printing functions */
-#include <libipset/types.h> /* prototypes */
-
-/* Parse commandline arguments */
-static const struct ipset_arg hash_net_create_args[] = {
- { .name = { "family", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_FAMILY,
- .parse = ipset_parse_family, .print = ipset_print_family,
- },
- /* Alias: family inet */
- { .name = { "-4", NULL },
- .has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY,
- .parse = ipset_parse_family,
- },
- /* Alias: family inet6 */
- { .name = { "-6", NULL },
- .has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY,
- .parse = ipset_parse_family,
- },
- { .name = { "hashsize", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_HASHSIZE,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- { .name = { "maxelem", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_MAXELEM,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- { .name = { "timeout", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- /* Ignored options: backward compatibilty */
- { .name = { "probes", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_PROBES,
- .parse = ipset_parse_ignored, .print = ipset_print_number,
- },
- { .name = { "resize", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_RESIZE,
- .parse = ipset_parse_ignored, .print = ipset_print_number,
- },
- { },
-};
-
-static const struct ipset_arg hash_net_add_args[] = {
- { .name = { "timeout", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- { },
-};
-
-static const char hash_net0_usage[] =
-"create SETNAME hash:net\n"
-" [family inet|inet6]\n"
-" [hashsize VALUE] [maxelem VALUE]\n"
-" [timeout VALUE]\n"
-"add SETNAME IP[/CIDR] [timeout VALUE]\n"
-"del SETNAME IP[/CIDR]\n"
-"test SETNAME IP[/CIDR]\n\n"
-"where depending on the INET family\n"
-" IP is an IPv4 or IPv6 address (or hostname),\n"
-" CIDR is a valid IPv4 or IPv6 CIDR prefix.\n";
-
-struct ipset_type ipset_hash_net0 = {
- .name = "hash:net",
- .alias = { "nethash", NULL },
- .revision = 0,
- .family = NFPROTO_IPSET_IPV46,
- .dimension = IPSET_DIM_ONE,
- .elem = {
- [IPSET_DIM_ONE - 1] = {
- .parse = ipset_parse_ipnet,
- .print = ipset_print_ip,
- .opt = IPSET_OPT_IP
- },
- },
- .args = {
- [IPSET_CREATE] = hash_net_create_args,
- [IPSET_ADD] = hash_net_add_args,
- },
- .mandatory = {
- [IPSET_CREATE] = 0,
- [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP),
- [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP),
- [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP),
- },
- .full = {
- [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE)
- | IPSET_FLAG(IPSET_OPT_MAXELEM)
- | IPSET_FLAG(IPSET_OPT_TIMEOUT),
- [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_CIDR)
- | IPSET_FLAG(IPSET_OPT_TIMEOUT),
- [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_CIDR),
- [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_CIDR),
- },
-
- .usage = hash_net0_usage,
-};
-
-static const char hash_net1_usage[] =
-"create SETNAME hash:net\n"
-" [family inet|inet6]\n"
-" [hashsize VALUE] [maxelem VALUE]\n"
-" [timeout VALUE]\n"
-"add SETNAME IP[/CIDR]|FROM-TO [timeout VALUE]\n"
-"del SETNAME IP[/CIDR]|FROM-TO\n"
-"test SETNAME IP[/CIDR]\n\n"
-"where depending on the INET family\n"
-" IP is an IPv4 or IPv6 address (or hostname),\n"
-" CIDR is a valid IPv4 or IPv6 CIDR prefix.\n"
-" IP range is not supported with IPv6.\n";
-
-struct ipset_type ipset_hash_net1 = {
- .name = "hash:net",
- .alias = { "nethash", NULL },
- .revision = 1,
- .family = NFPROTO_IPSET_IPV46,
- .dimension = IPSET_DIM_ONE,
- .elem = {
- [IPSET_DIM_ONE - 1] = {
- .parse = ipset_parse_ip4_net6,
- .print = ipset_print_ip,
- .opt = IPSET_OPT_IP
- },
- },
- .args = {
- [IPSET_CREATE] = hash_net_create_args,
- [IPSET_ADD] = hash_net_add_args,
- },
- .mandatory = {
- [IPSET_CREATE] = 0,
- [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP),
- [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP),
- [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP),
- },
- .full = {
- [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE)
- | IPSET_FLAG(IPSET_OPT_MAXELEM)
- | IPSET_FLAG(IPSET_OPT_TIMEOUT),
- [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_CIDR)
- | IPSET_FLAG(IPSET_OPT_IP_TO)
- | IPSET_FLAG(IPSET_OPT_TIMEOUT),
- [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_CIDR)
- | IPSET_FLAG(IPSET_OPT_IP_TO),
- [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_CIDR),
- },
-
- .usage = hash_net1_usage,
-};
-
+++ /dev/null
-/* Copyright 2011 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <libipset/data.h> /* IPSET_OPT_* */
-#include <libipset/parse.h> /* parser functions */
-#include <libipset/print.h> /* printing functions */
-#include <libipset/ui.h> /* ipset_port_usage */
-#include <libipset/types.h> /* prototypes */
-
-/* Parse commandline arguments */
-static const struct ipset_arg hash_netiface_create_args[] = {
- { .name = { "family", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_FAMILY,
- .parse = ipset_parse_family, .print = ipset_print_family,
- },
- /* Alias: family inet */
- { .name = { "-4", NULL },
- .has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY,
- .parse = ipset_parse_family,
- },
- /* Alias: family inet6 */
- { .name = { "-6", NULL },
- .has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY,
- .parse = ipset_parse_family,
- },
- { .name = { "hashsize", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_HASHSIZE,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- { .name = { "maxelem", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_MAXELEM,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- { .name = { "timeout", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- { },
-};
-
-static const struct ipset_arg hash_netiface_add_args[] = {
- { .name = { "timeout", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- { },
-};
-
-static const char hash_netiface_usage[] =
-"create SETNAME hash:net,iface\n"
-" [family inet|inet6]\n"
-" [hashsize VALUE] [maxelem VALUE]\n"
-" [timeout VALUE]\n"
-"add SETNAME IP[/CIDR]|FROM-TO,[physdev:]IFACE [timeout VALUE]\n"
-"del SETNAME IP[/CIDR]|FROM-TO,[physdev:]IFACE\n"
-"test SETNAME IP[/CIDR],[physdev:]IFACE\n\n"
-"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 IPv4 is supported.\n";
-
-struct ipset_type ipset_hash_netiface0 = {
- .name = "hash:net,iface",
- .alias = { "netifacehash", NULL },
- .revision = 0,
- .family = NFPROTO_IPSET_IPV46,
- .dimension = IPSET_DIM_TWO,
- .elem = {
- [IPSET_DIM_ONE - 1] = {
- .parse = ipset_parse_ip4_net6,
- .print = ipset_print_ip,
- .opt = IPSET_OPT_IP
- },
- [IPSET_DIM_TWO - 1] = {
- .parse = ipset_parse_iface,
- .print = ipset_print_iface,
- .opt = IPSET_OPT_IFACE
- },
- },
- .args = {
- [IPSET_CREATE] = hash_netiface_create_args,
- [IPSET_ADD] = hash_netiface_add_args,
- },
- .mandatory = {
- [IPSET_CREATE] = 0,
- [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_IFACE),
- [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_IFACE),
- [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_IFACE),
- },
- .full = {
- [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE)
- | IPSET_FLAG(IPSET_OPT_MAXELEM)
- | IPSET_FLAG(IPSET_OPT_TIMEOUT),
- [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_CIDR)
- | IPSET_FLAG(IPSET_OPT_IP_TO)
- | IPSET_FLAG(IPSET_OPT_IFACE)
- | IPSET_FLAG(IPSET_OPT_PHYSDEV)
- | IPSET_FLAG(IPSET_OPT_TIMEOUT),
- [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_CIDR)
- | IPSET_FLAG(IPSET_OPT_IP_TO)
- | IPSET_FLAG(IPSET_OPT_IFACE)
- | IPSET_FLAG(IPSET_OPT_PHYSDEV),
- [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_CIDR)
- | IPSET_FLAG(IPSET_OPT_IP_TO)
- | IPSET_FLAG(IPSET_OPT_IFACE)
- | IPSET_FLAG(IPSET_OPT_PHYSDEV),
- },
-
- .usage = hash_netiface_usage,
-};
-
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <libipset/data.h> /* IPSET_OPT_* */
-#include <libipset/parse.h> /* parser functions */
-#include <libipset/print.h> /* printing functions */
-#include <libipset/ui.h> /* ipset_port_usage */
-#include <libipset/types.h> /* prototypes */
-
-/* Parse commandline arguments */
-static const struct ipset_arg hash_netport_create_args[] = {
- { .name = { "family", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_FAMILY,
- .parse = ipset_parse_family, .print = ipset_print_family,
- },
- /* Alias: family inet */
- { .name = { "-4", NULL },
- .has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY,
- .parse = ipset_parse_family,
- },
- /* Alias: family inet6 */
- { .name = { "-6", NULL },
- .has_arg = IPSET_NO_ARG, .opt = IPSET_OPT_FAMILY,
- .parse = ipset_parse_family,
- },
- { .name = { "hashsize", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_HASHSIZE,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- { .name = { "maxelem", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_MAXELEM,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- { .name = { "timeout", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- { },
-};
-
-static const struct ipset_arg hash_netport_add_args[] = {
- { .name = { "timeout", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- { },
-};
-
-static const char hash_netport1_usage[] =
-"create SETNAME hash:net,port\n"
-" [family inet|inet6]\n"
-" [hashsize VALUE] [maxelem VALUE]\n"
-" [timeout VALUE]\n"
-"add SETNAME IP[/CIDR],PROTO:PORT [timeout VALUE]\n"
-"del SETNAME IP[/CIDR],PROTO:PORT\n"
-"test SETNAME IP[/CIDR],PROTO:PORT\n\n"
-"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/SCTP/UDP/UDPLITE\n"
-" port range is supported both for IPv4 and IPv6.\n";
-
-struct ipset_type ipset_hash_netport1 = {
- .name = "hash:net,port",
- .alias = { "netporthash", NULL },
- .revision = 1,
- .family = NFPROTO_IPSET_IPV46,
- .dimension = IPSET_DIM_TWO,
- .elem = {
- [IPSET_DIM_ONE - 1] = {
- .parse = ipset_parse_ipnet,
- .print = ipset_print_ip,
- .opt = IPSET_OPT_IP
- },
- [IPSET_DIM_TWO - 1] = {
- .parse = ipset_parse_proto_port,
- .print = ipset_print_proto_port,
- .opt = IPSET_OPT_PORT
- },
- },
- .args = {
- [IPSET_CREATE] = hash_netport_create_args,
- [IPSET_ADD] = hash_netport_add_args,
- },
- .mandatory = {
- [IPSET_CREATE] = 0,
- [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_PROTO)
- | IPSET_FLAG(IPSET_OPT_PORT),
- [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_PROTO)
- | IPSET_FLAG(IPSET_OPT_PORT),
- [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_PROTO)
- | IPSET_FLAG(IPSET_OPT_PORT),
- },
- .full = {
- [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE)
- | IPSET_FLAG(IPSET_OPT_MAXELEM)
- | IPSET_FLAG(IPSET_OPT_TIMEOUT),
- [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_PORT)
- | IPSET_FLAG(IPSET_OPT_PORT_TO)
- | IPSET_FLAG(IPSET_OPT_PROTO)
- | IPSET_FLAG(IPSET_OPT_TIMEOUT)
- | IPSET_FLAG(IPSET_OPT_CIDR),
- [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_PORT)
- | IPSET_FLAG(IPSET_OPT_PORT_TO)
- | IPSET_FLAG(IPSET_OPT_PROTO)
- | IPSET_FLAG(IPSET_OPT_CIDR),
- [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_PORT)
- | IPSET_FLAG(IPSET_OPT_PROTO)
- | IPSET_FLAG(IPSET_OPT_CIDR),
- },
-
- .usage = hash_netport1_usage,
- .usagefn = ipset_port_usage,
-};
-
-static const char hash_netport2_usage[] =
-"create SETNAME hash:net,port\n"
-" [family inet|inet6]\n"
-" [hashsize VALUE] [maxelem VALUE]\n"
-" [timeout VALUE]\n"
-"add SETNAME IP[/CIDR]|FROM-TO,PROTO:PORT [timeout VALUE]\n"
-"del SETNAME IP[/CIDR]|FROM-TO,PROTO:PORT\n"
-"test SETNAME IP[/CIDR],PROTO:PORT\n\n"
-"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 IPv4 is 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_netport2 = {
- .name = "hash:net,port",
- .alias = { "netporthash", NULL },
- .revision = 2,
- .family = NFPROTO_IPSET_IPV46,
- .dimension = IPSET_DIM_TWO,
- .elem = {
- [IPSET_DIM_ONE - 1] = {
- .parse = ipset_parse_ip4_net6,
- .print = ipset_print_ip,
- .opt = IPSET_OPT_IP
- },
- [IPSET_DIM_TWO - 1] = {
- .parse = ipset_parse_proto_port,
- .print = ipset_print_proto_port,
- .opt = IPSET_OPT_PORT
- },
- },
- .args = {
- [IPSET_CREATE] = hash_netport_create_args,
- [IPSET_ADD] = hash_netport_add_args,
- },
- .mandatory = {
- [IPSET_CREATE] = 0,
- [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_PROTO)
- | IPSET_FLAG(IPSET_OPT_PORT),
- [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_PROTO)
- | IPSET_FLAG(IPSET_OPT_PORT),
- [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_PROTO)
- | IPSET_FLAG(IPSET_OPT_PORT),
- },
- .full = {
- [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_HASHSIZE)
- | IPSET_FLAG(IPSET_OPT_MAXELEM)
- | IPSET_FLAG(IPSET_OPT_TIMEOUT),
- [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_CIDR)
- | IPSET_FLAG(IPSET_OPT_IP_TO)
- | IPSET_FLAG(IPSET_OPT_PORT)
- | IPSET_FLAG(IPSET_OPT_PORT_TO)
- | IPSET_FLAG(IPSET_OPT_PROTO)
- | IPSET_FLAG(IPSET_OPT_TIMEOUT),
- [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_CIDR)
- | IPSET_FLAG(IPSET_OPT_IP_TO)
- | IPSET_FLAG(IPSET_OPT_PORT)
- | IPSET_FLAG(IPSET_OPT_PORT_TO)
- | IPSET_FLAG(IPSET_OPT_PROTO),
- [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_IP)
- | IPSET_FLAG(IPSET_OPT_CIDR)
- | IPSET_FLAG(IPSET_OPT_PORT)
- | IPSET_FLAG(IPSET_OPT_PROTO),
- },
-
- .usage = hash_netport2_usage,
- .usagefn = ipset_port_usage,
-};
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <libipset/data.h> /* IPSET_OPT_* */
-#include <libipset/parse.h> /* parser functions */
-#include <libipset/print.h> /* printing functions */
-#include <libipset/types.h> /* prototypes */
-
-/* Parse commandline arguments */
-static const struct ipset_arg list_set_create_args[] = {
- { .name = { "size", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_SIZE,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- { .name = { "timeout", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- { },
-};
-
-static const struct ipset_arg list_set_adt_args[] = {
- { .name = { "timeout", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_TIMEOUT,
- .parse = ipset_parse_uint32, .print = ipset_print_number,
- },
- { .name = { "before", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_NAMEREF,
- .parse = ipset_parse_before,
- },
- { .name = { "after", NULL },
- .has_arg = IPSET_MANDATORY_ARG, .opt = IPSET_OPT_NAMEREF,
- .parse = ipset_parse_after,
- },
- { },
-};
-
-static const char list_set_usage[] =
-"create SETNAME list:set\n"
-" [size VALUE] [timeout VALUE]\n"
-"add SETNAME NAME [before|after NAME] [timeout VALUE]\n"
-"del SETNAME NAME [before|after NAME]\n"
-"test SETNAME NAME [before|after NAME]\n\n"
-"where NAME are existing set names.\n";
-
-struct ipset_type ipset_list_set0 = {
- .name = "list:set",
- .alias = { "setlist", NULL },
- .revision = 0,
- .family = NFPROTO_UNSPEC,
- .dimension = IPSET_DIM_ONE,
- .elem = {
- [IPSET_DIM_ONE - 1] = {
- .parse = ipset_parse_setname,
- .print = ipset_print_name,
- .opt = IPSET_OPT_NAME
- },
- },
- .compat_parse_elem = ipset_parse_name_compat,
- .args = {
- [IPSET_CREATE] = list_set_create_args,
- [IPSET_ADD] = list_set_adt_args,
- [IPSET_DEL] = list_set_adt_args,
- [IPSET_TEST] = list_set_adt_args,
- },
- .mandatory = {
- [IPSET_CREATE] = 0,
- [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_NAME),
- [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_NAME),
- [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_NAME),
- },
- .full = {
- [IPSET_CREATE] = IPSET_FLAG(IPSET_OPT_SIZE)
- | IPSET_FLAG(IPSET_OPT_TIMEOUT),
- [IPSET_ADD] = IPSET_FLAG(IPSET_OPT_NAME)
- | IPSET_FLAG(IPSET_OPT_BEFORE)
- | IPSET_FLAG(IPSET_OPT_NAMEREF)
- | IPSET_FLAG(IPSET_OPT_TIMEOUT),
- [IPSET_DEL] = IPSET_FLAG(IPSET_OPT_NAME)
- | IPSET_FLAG(IPSET_OPT_BEFORE)
- | IPSET_FLAG(IPSET_OPT_NAMEREF),
- [IPSET_TEST] = IPSET_FLAG(IPSET_OPT_NAME)
- | IPSET_FLAG(IPSET_OPT_BEFORE)
- | IPSET_FLAG(IPSET_OPT_NAMEREF),
- },
-
- .usage = list_set_usage,
-};
+++ /dev/null
-/* Copyright 2007-2010 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <assert.h> /* assert */
-#include <ctype.h> /* tolower */
-#include <string.h> /* memcmp, str* */
-
-#include <libipset/linux_ip_set.h> /* IPSET_CMD_* */
-#include <libipset/icmp.h> /* id_to_icmp */
-#include <libipset/icmpv6.h> /* id_to_icmpv6 */
-#include <libipset/types.h> /* IPSET_*_ARG */
-#include <libipset/session.h> /* ipset_envopt_parse */
-#include <libipset/parse.h> /* ipset_parse_family */
-#include <libipset/print.h> /* ipset_print_family */
-#include <libipset/utils.h> /* STREQ */
-#include <libipset/ui.h> /* prototypes */
-
-/* Commands and environment options */
-
-const struct ipset_commands ipset_commands[] = {
- /* Order is important */
-
- { /* c[reate], --create, n[ew], -N */
- .cmd = IPSET_CMD_CREATE,
- .name = { "create", "new" },
- .has_arg = IPSET_MANDATORY_ARG2,
- .help = "SETNAME TYPENAME [type-specific-options]\n"
- " Create a new set",
- },
- { /* a[dd], --add, -A */
- .cmd = IPSET_CMD_ADD,
- .name = { "add", NULL },
- .has_arg = IPSET_MANDATORY_ARG2,
- .help = "SETNAME ENTRY\n"
- " Add entry to the named set",
- },
- { /* d[el], --del, -D */
- .cmd = IPSET_CMD_DEL,
- .name = { "del", NULL },
- .has_arg = IPSET_MANDATORY_ARG2,
- .help = "SETNAME ENTRY\n"
- " Delete entry from the named set",
- },
- { /* t[est], --test, -T */
- .cmd = IPSET_CMD_TEST,
- .name = { "test", NULL },
- .has_arg = IPSET_MANDATORY_ARG2,
- .help = "SETNAME ENTRY\n"
- " Test entry in the named set",
- },
- { /* des[troy], --destroy, x, -X */
- .cmd = IPSET_CMD_DESTROY,
- .name = { "destroy", "x" },
- .has_arg = IPSET_OPTIONAL_ARG,
- .help = "[SETNAME]\n"
- " Destroy a named set or all sets",
- },
- { /* l[ist], --list, -L */
- .cmd = IPSET_CMD_LIST,
- .name = { "list", NULL },
- .has_arg = IPSET_OPTIONAL_ARG,
- .help = "[SETNAME]\n"
- " List the entries of a named set or all sets",
- },
- { /* s[save], --save, -S */
- .cmd = IPSET_CMD_SAVE,
- .name = { "save", NULL },
- .has_arg = IPSET_OPTIONAL_ARG,
- .help = "[SETNAME]\n"
- " Save the named set or all sets to stdout",
- },
- { /* r[estore], --restore, -R */
- .cmd = IPSET_CMD_RESTORE,
- .name = { "restore", NULL },
- .has_arg = IPSET_NO_ARG,
- .help = "\n"
- " Restore a saved state",
- },
- { /* f[lush], --flush, -F */
- .cmd = IPSET_CMD_FLUSH,
- .name = { "flush", NULL },
- .has_arg = IPSET_OPTIONAL_ARG,
- .help = "[SETNAME]\n"
- " Flush a named set or all sets",
- },
- { /* ren[ame], --rename, e, -E */
- .cmd = IPSET_CMD_RENAME,
- .name = { "rename", "e" },
- .has_arg = IPSET_MANDATORY_ARG2,
- .help = "FROM-SETNAME TO-SETNAME\n"
- " Rename two sets",
- },
- { /* sw[ap], --swap, w, -W */
- .cmd = IPSET_CMD_SWAP,
- .name = { "swap", "w" },
- .has_arg = IPSET_MANDATORY_ARG2,
- .help = "FROM-SETNAME TO-SETNAME\n"
- " Swap the contect of two existing sets",
- },
- { /* h[elp, --help, -H */
- .cmd = IPSET_CMD_HELP,
- .name = { "help", NULL },
- .has_arg = IPSET_OPTIONAL_ARG,
- .help = "[TYPENAME]\n"
- " Print help, and settype specific help",
- },
- { /* v[ersion], --version, -V */
- .cmd = IPSET_CMD_VERSION,
- .name = { "version", NULL },
- .has_arg = IPSET_NO_ARG,
- .help = "\n"
- " Print version information",
- },
- { /* q[uit] */
- .cmd = IPSET_CMD_QUIT,
- .name = { "quit", NULL },
- .has_arg = IPSET_NO_ARG,
- .help = "\n"
- " Quit interactive mode",
- },
- { },
-};
-
-/* Match a command: try to match as a prefix or letter-command */
-bool
-ipset_match_cmd(const char *arg, const char * const name[])
-{
- size_t len;
-
- assert(arg);
- assert(name && name[0]);
-
- /* Ignore (two) leading dashes */
- if (arg[0] == '-')
- arg++;
- if (arg[0] == '-')
- arg++;
-
- len = strlen(arg);
-
- if (len > strlen(name[0]) || !len)
- return false;
- 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
- return tolower(arg[0]) == name[0][0] ||
- (name[1] != NULL && tolower(arg[0]) == name[1][0]);
-}
-
-const struct ipset_envopts ipset_envopts[] = {
- { .name = { "-o", "-output" },
- .has_arg = IPSET_MANDATORY_ARG, .flag = IPSET_OPT_MAX,
- .parse = ipset_parse_output,
- .help = "plain|save|xml\n"
- " Specify output mode for listing sets.\n"
- " Default value for \"list\" command is mode \"plain\"\n"
- " and for \"save\" command is mode \"save\".",
- },
- { .name = { "-s", "-sorted" },
- .parse = ipset_envopt_parse,
- .has_arg = IPSET_NO_ARG, .flag = IPSET_ENV_SORTED,
- .help = "\n"
- " Print elements sorted (if supported by the set type).",
- },
- { .name = { "-q", "-quiet" },
- .parse = ipset_envopt_parse,
- .has_arg = IPSET_NO_ARG, .flag = IPSET_ENV_QUIET,
- .help = "\n"
- " Suppress any notice or warning message.",
- },
- { .name = { "-r", "-resolve" },
- .parse = ipset_envopt_parse,
- .has_arg = IPSET_NO_ARG, .flag = IPSET_ENV_RESOLVE,
- .help = "\n"
- " Try to resolve IP addresses in the output (slow!)",
- },
- { .name = { "-!", "-exist" },
- .parse = ipset_envopt_parse,
- .has_arg = IPSET_NO_ARG, .flag = IPSET_ENV_EXIST,
- .help = "\n"
- " Ignore errors when creating already created sets,\n"
- " when adding already existing elements\n"
- " or when deleting non-existing elements.",
- },
- { .name = { "-n", "-name" },
- .parse = ipset_envopt_parse,
- .has_arg = IPSET_NO_ARG, .flag = IPSET_ENV_LIST_SETNAME,
- .help = "\n"
- " When listing, list just setnames from kernel.\n",
- },
- { .name = { "-t", "-terse" },
- .parse = ipset_envopt_parse,
- .has_arg = IPSET_NO_ARG, .flag = IPSET_ENV_LIST_HEADER,
- .help = "\n"
- " When listing, list setnames and set headers\n"
- " from kernel only.",
- },
- { },
-};
-
-/* Strict option matching */
-bool
-ipset_match_option(const char *arg, const char * const name[])
-{
- assert(arg);
- assert(name && name[0]);
-
- /* Skip two leading dashes */
- if (arg[0] == '-' && arg[1] == '-')
- arg++, arg++;
-
- return STREQ(arg, name[0]) ||
- (name[1] != NULL && STREQ(arg, name[1]));
-}
-
-/* Strict envopt matching */
-bool
-ipset_match_envopt(const char *arg, const char * const name[])
-{
- assert(arg);
- assert(name && name[0]);
-
- /* Skip one leading dash */
- if (arg[0] == '-' && arg[1] == '-')
- arg++;
-
- return STREQ(arg, name[0]) ||
- (name[1] != NULL && STREQ(arg, name[1]));
-}
-
-/**
- * ipset_shift_argv - shift off an argument
- * @arc: argument count
- * @argv: array of argument strings
- * @from: from where shift off an argument
- *
- * Shift off the argument at "from" from the array of
- * arguments argv of size argc.
- */
-void
-ipset_shift_argv(int *argc, char *argv[], int from)
-{
- int i;
-
- assert(*argc >= from + 1);
-
- for (i = from + 1; i <= *argc; i++)
- argv[i-1] = argv[i];
- (*argc)--;
- return;
-}
-
-/**
- * ipset_port_usage - prints the usage for the port parameter
- *
- * Print the usage for the port parameter to stdout.
- */
-void
-ipset_port_usage(void)
-{
- int i;
- const char *name;
-
- printf(" [PROTO:]PORT is a valid pattern of the following:\n"
- " PORTNAME TCP port name from /etc/services\n"
- " PORTNUMBER TCP port number identifier\n"
- " tcp|sctp|udp|udplite:PORTNAME|PORTNUMBER\n"
- " icmp:CODENAME supported ICMP codename\n"
- " icmp:TYPE/CODE ICMP type/code value\n"
- " icmpv6:CODENAME supported ICMPv6 codename\n"
- " icmpv6:TYPE/CODE ICMPv6 type/code value\n"
- " PROTO:0 all other protocols\n\n");
-
- printf(" Supported ICMP codenames:\n");
- i = 0;
- while ((name = id_to_icmp(i++)) != NULL)
- printf(" %s\n", name);
- printf(" Supported ICMPv6 codenames:\n");
- i = 0;
- while ((name = id_to_icmpv6(i++)) != NULL)
- printf(" %s\n", name);
-}
+++ /dev/null
-/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
- * Patrick Schaaf <bof@bof.de>
- * Martin Josefsson <gandalf@wlug.westbo.se>
- * Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-/* Kernel module which implements the set match and SET target
- * for netfilter/iptables. */
-
-#include <linux/module.h>
-#include <linux/skbuff.h>
-
-#include <linux/netfilter/x_tables.h>
-#include "xt_set.h"
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
-MODULE_DESCRIPTION("Xtables: IP set match and target module");
-MODULE_ALIAS("xt_SET");
-MODULE_ALIAS("ipt_set");
-MODULE_ALIAS("ip6t_set");
-MODULE_ALIAS("ipt_SET");
-MODULE_ALIAS("ip6t_SET");
-
-static inline int
-match_set(ip_set_id_t index, const struct sk_buff *skb,
- const struct xt_action_param *par,
- const struct ip_set_adt_opt *opt, int inv)
-{
- if (ip_set_test(index, skb, par, opt))
- inv = !inv;
- return inv;
-}
-
-#define ADT_OPT(n, f, d, fs, cfs, t) \
-const struct ip_set_adt_opt n = { \
- .family = f, \
- .dim = d, \
- .flags = fs, \
- .cmdflags = cfs, \
- .timeout = t, \
-}
-
-/* Revision 0 interface: backward compatible with netfilter/iptables */
-
-static bool
-set_match_v0(const struct sk_buff *skb, struct xt_action_param *par)
-{
- const struct xt_set_info_match_v0 *info = par->matchinfo;
- ADT_OPT(opt, par->family, info->match_set.u.compat.dim,
- info->match_set.u.compat.flags, 0, UINT_MAX);
-
- return match_set(info->match_set.index, skb, par, &opt,
- info->match_set.u.compat.flags & IPSET_INV_MATCH);
-}
-
-static void
-compat_flags(struct xt_set_info_v0 *info)
-{
- u_int8_t i;
-
- /* Fill out compatibility data according to enum ip_set_kopt */
- info->u.compat.dim = IPSET_DIM_ZERO;
- if (info->u.flags[0] & IPSET_MATCH_INV)
- info->u.compat.flags |= IPSET_INV_MATCH;
- for (i = 0; i < IPSET_DIM_MAX-1 && info->u.flags[i]; i++) {
- info->u.compat.dim++;
- if (info->u.flags[i] & IPSET_SRC)
- info->u.compat.flags |= (1<<info->u.compat.dim);
- }
-}
-
-static int
-set_match_v0_checkentry(const struct xt_mtchk_param *par)
-{
- struct xt_set_info_match_v0 *info = par->matchinfo;
- ip_set_id_t index;
-
- index = ip_set_nfnl_get_byindex(info->match_set.index);
-
- if (index == IPSET_INVALID_ID) {
- pr_warning("Cannot find set indentified by id %u to match\n",
- info->match_set.index);
- return -ENOENT;
- }
- 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 -ERANGE;
- }
-
- /* Fill out compatibility data */
- compat_flags(&info->match_set);
-
- return 0;
-}
-
-static void
-set_match_v0_destroy(const struct xt_mtdtor_param *par)
-{
- struct xt_set_info_match_v0 *info = par->matchinfo;
-
- ip_set_nfnl_put(info->match_set.index);
-}
-
-static unsigned int
-set_target_v0(struct sk_buff *skb, const struct xt_action_param *par)
-{
- const struct xt_set_info_target_v0 *info = par->targinfo;
- ADT_OPT(add_opt, par->family, info->add_set.u.compat.dim,
- info->add_set.u.compat.flags, 0, UINT_MAX);
- ADT_OPT(del_opt, par->family, info->del_set.u.compat.dim,
- info->del_set.u.compat.flags, 0, UINT_MAX);
-
- if (info->add_set.index != IPSET_INVALID_ID)
- ip_set_add(info->add_set.index, skb, par, &add_opt);
- if (info->del_set.index != IPSET_INVALID_ID)
- ip_set_del(info->del_set.index, skb, par, &del_opt);
-
- return XT_CONTINUE;
-}
-
-static int
-set_target_v0_checkentry(const struct xt_tgchk_param *par)
-{
- struct xt_set_info_target_v0 *info = par->targinfo;
- ip_set_id_t index;
-
- 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",
- info->add_set.index);
- return -ENOENT;
- }
- }
-
- 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",
- info->del_set.index);
- if (info->add_set.index != IPSET_INVALID_ID)
- ip_set_nfnl_put(info->add_set.index);
- return -ENOENT;
- }
- }
- if (info->add_set.u.flags[IPSET_DIM_MAX-1] != 0 ||
- 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 -ERANGE;
- }
-
- /* Fill out compatibility data */
- compat_flags(&info->add_set);
- compat_flags(&info->del_set);
-
- return 0;
-}
-
-static void
-set_target_v0_destroy(const struct xt_tgdtor_param *par)
-{
- const struct xt_set_info_target_v0 *info = par->targinfo;
-
- 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);
-}
-
-/* Revision 1 match and target */
-
-static bool
-set_match_v1(const struct sk_buff *skb, struct xt_action_param *par)
-{
- const struct xt_set_info_match_v1 *info = par->matchinfo;
- ADT_OPT(opt, par->family, info->match_set.dim,
- info->match_set.flags, 0, UINT_MAX);
-
- return match_set(info->match_set.index, skb, par, &opt,
- info->match_set.flags & IPSET_INV_MATCH);
-}
-
-static int
-set_match_v1_checkentry(const struct xt_mtchk_param *par)
-{
- struct xt_set_info_match_v1 *info = par->matchinfo;
- ip_set_id_t index;
-
- index = ip_set_nfnl_get_byindex(info->match_set.index);
-
- if (index == IPSET_INVALID_ID) {
- pr_warning("Cannot find set indentified by id %u to match\n",
- info->match_set.index);
- return -ENOENT;
- }
- 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 -ERANGE;
- }
-
- return 0;
-}
-
-static void
-set_match_v1_destroy(const struct xt_mtdtor_param *par)
-{
- struct xt_set_info_match_v1 *info = par->matchinfo;
-
- ip_set_nfnl_put(info->match_set.index);
-}
-
-static unsigned int
-set_target_v1(struct sk_buff *skb, const struct xt_action_param *par)
-{
- const struct xt_set_info_target_v1 *info = par->targinfo;
- ADT_OPT(add_opt, par->family, info->add_set.dim,
- info->add_set.flags, 0, UINT_MAX);
- ADT_OPT(del_opt, par->family, info->del_set.dim,
- info->del_set.flags, 0, UINT_MAX);
-
- if (info->add_set.index != IPSET_INVALID_ID)
- ip_set_add(info->add_set.index, skb, par, &add_opt);
- if (info->del_set.index != IPSET_INVALID_ID)
- ip_set_del(info->del_set.index, skb, par, &del_opt);
-
- return XT_CONTINUE;
-}
-
-static int
-set_target_v1_checkentry(const struct xt_tgchk_param *par)
-{
- const struct xt_set_info_target_v1 *info = par->targinfo;
- ip_set_id_t index;
-
- 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",
- info->add_set.index);
- return -ENOENT;
- }
- }
-
- 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",
- info->del_set.index);
- if (info->add_set.index != IPSET_INVALID_ID)
- ip_set_nfnl_put(info->add_set.index);
- return -ENOENT;
- }
- }
- if (info->add_set.dim > 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 -ERANGE;
- }
-
- return 0;
-}
-
-static void
-set_target_v1_destroy(const struct xt_tgdtor_param *par)
-{
- const struct xt_set_info_target_v1 *info = par->targinfo;
-
- 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);
-}
-
-/* Revision 2 target */
-
-static unsigned int
-set_target_v2(struct sk_buff *skb, const struct xt_action_param *par)
-{
- const struct xt_set_info_target_v2 *info = par->targinfo;
- ADT_OPT(add_opt, par->family, info->add_set.dim,
- info->add_set.flags, info->flags, info->timeout);
- ADT_OPT(del_opt, par->family, info->del_set.dim,
- info->del_set.flags, 0, UINT_MAX);
-
- if (info->add_set.index != IPSET_INVALID_ID)
- ip_set_add(info->add_set.index, skb, par, &add_opt);
- if (info->del_set.index != IPSET_INVALID_ID)
- ip_set_del(info->del_set.index, skb, par, &del_opt);
-
- return XT_CONTINUE;
-}
-
-#define set_target_v2_checkentry set_target_v1_checkentry
-#define set_target_v2_destroy set_target_v1_destroy
-
-static struct xt_match set_matches[] __read_mostly = {
- {
- .name = "set",
- .family = NFPROTO_IPV4,
- .revision = 0,
- .match = set_match_v0,
- .matchsize = sizeof(struct xt_set_info_match_v0),
- .checkentry = set_match_v0_checkentry,
- .destroy = set_match_v0_destroy,
- .me = THIS_MODULE
- },
- {
- .name = "set",
- .family = NFPROTO_IPV4,
- .revision = 1,
- .match = set_match_v1,
- .matchsize = sizeof(struct xt_set_info_match_v1),
- .checkentry = set_match_v1_checkentry,
- .destroy = set_match_v1_destroy,
- .me = THIS_MODULE
- },
- {
- .name = "set",
- .family = NFPROTO_IPV6,
- .revision = 1,
- .match = set_match_v1,
- .matchsize = sizeof(struct xt_set_info_match_v1),
- .checkentry = set_match_v1_checkentry,
- .destroy = set_match_v1_destroy,
- .me = THIS_MODULE
- },
-};
-
-static struct xt_target set_targets[] __read_mostly = {
- {
- .name = "SET",
- .revision = 0,
- .family = NFPROTO_IPV4,
- .target = set_target_v0,
- .targetsize = sizeof(struct xt_set_info_target_v0),
- .checkentry = set_target_v0_checkentry,
- .destroy = set_target_v0_destroy,
- .me = THIS_MODULE
- },
- {
- .name = "SET",
- .revision = 1,
- .family = NFPROTO_IPV4,
- .target = set_target_v1,
- .targetsize = sizeof(struct xt_set_info_target_v1),
- .checkentry = set_target_v1_checkentry,
- .destroy = set_target_v1_destroy,
- .me = THIS_MODULE
- },
- {
- .name = "SET",
- .revision = 1,
- .family = NFPROTO_IPV6,
- .target = set_target_v1,
- .targetsize = sizeof(struct xt_set_info_target_v1),
- .checkentry = set_target_v1_checkentry,
- .destroy = set_target_v1_destroy,
- .me = THIS_MODULE
- },
- {
- .name = "SET",
- .revision = 2,
- .family = NFPROTO_IPV4,
- .target = set_target_v2,
- .targetsize = sizeof(struct xt_set_info_target_v2),
- .checkentry = set_target_v2_checkentry,
- .destroy = set_target_v2_destroy,
- .me = THIS_MODULE
- },
- {
- .name = "SET",
- .revision = 2,
- .family = NFPROTO_IPV6,
- .target = set_target_v2,
- .targetsize = sizeof(struct xt_set_info_target_v2),
- .checkentry = set_target_v2_checkentry,
- .destroy = set_target_v2_destroy,
- .me = THIS_MODULE
- },
-};
-
-static int __init xt_set_init(void)
-{
- int ret = xt_register_matches(set_matches, ARRAY_SIZE(set_matches));
-
- if (!ret) {
- ret = xt_register_targets(set_targets,
- ARRAY_SIZE(set_targets));
- if (ret)
- xt_unregister_matches(set_matches,
- ARRAY_SIZE(set_matches));
- }
- return ret;
-}
-
-static void __exit xt_set_fini(void)
-{
- xt_unregister_matches(set_matches, ARRAY_SIZE(set_matches));
- xt_unregister_targets(set_targets, ARRAY_SIZE(set_targets));
-}
-
-module_init(xt_set_init);
-module_exit(xt_set_fini);
+++ /dev/null
-#ifndef _XT_SET_H
-#define _XT_SET_H
-
-#include <linux/types.h>
-#include "ip_set.h"
-
-/* Revision 0 interface: backward compatible with netfilter/iptables */
-
-/*
- * Option flags for kernel operations (xt_set_info_v0)
- */
-#define IPSET_SRC 0x01 /* Source match/add */
-#define IPSET_DST 0x02 /* Destination match/add */
-#define IPSET_MATCH_INV 0x04 /* Inverse matching */
-
-struct xt_set_info_v0 {
- ip_set_id_t index;
- union {
- __u32 flags[IPSET_DIM_MAX + 1];
- struct {
- __u32 __flags[IPSET_DIM_MAX];
- __u8 dim;
- __u8 flags;
- } compat;
- } u;
-};
-
-/* match and target infos */
-struct xt_set_info_match_v0 {
- struct xt_set_info_v0 match_set;
-};
-
-struct xt_set_info_target_v0 {
- struct xt_set_info_v0 add_set;
- struct xt_set_info_v0 del_set;
-};
-
-/* Revision 1 match and target */
-
-struct xt_set_info {
- ip_set_id_t index;
- __u8 dim;
- __u8 flags;
-};
-
-/* match and target infos */
-struct xt_set_info_match_v1 {
- struct xt_set_info match_set;
-};
-
-struct xt_set_info_target_v1 {
- struct xt_set_info add_set;
- struct xt_set_info del_set;
-};
-
-/* Revision 2 target */
-
-struct xt_set_info_target_v2 {
- struct xt_set_info add_set;
- struct xt_set_info del_set;
- __u32 flags;
- __u32 timeout;
-};
-
-#endif /*_XT_SET_H*/
build_gradm=m
build_iface=m
build_ipp2p=m
-build_ipset6=
build_ipv4options=m
build_length2=m
build_lscan=m