[nftables libnl] libnl: nf_tables: add support for set API
Patrick McHardy
netfilter-cvslog-bounces at lists.netfilter.org
Wed Apr 8 06:20:42 CEST 2009
Gitweb: http://git.netfilter.org/cgi-bin/gitweb.cgi?p=libnl-nft.git;a=commit;h=0917b23733f46c65703545f82cc633836436f13b
commit 0917b23733f46c65703545f82cc633836436f13b
Author: Patrick McHardy <kaber at trash.net>
AuthorDate: Wed Apr 8 06:19:09 2009 +0200
Commit: Patrick McHardy <kaber at trash.net>
CommitDate: Wed Apr 8 06:19:09 2009 +0200
libnl: nf_tables: add support for set API
Add support for the new set API to maintain sets independantly of the ruleset.
Signed-off-by: Patrick McHardy <kaber at trash.net>
via 0917b23733f46c65703545f82cc633836436f13b (commit)
from faa013b79cf0a723c78bad6f61e679fcb61f110f (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 0917b23733f46c65703545f82cc633836436f13b
Author: Patrick McHardy <kaber at trash.net>
Date: Wed Apr 8 06:19:09 2009 +0200
libnl: nf_tables: add support for set API
Add support for the new set API to maintain sets independantly of the ruleset.
Signed-off-by: Patrick McHardy <kaber at trash.net>
-----------------------------------------------------------------------
include/linux/netfilter/nf_tables.h | 374 +++++++++++++++++++++++++-----
include/netlink-types.h | 22 ++
include/netlink/netfilter/nft_expr.h | 78 +------
include/netlink/netfilter/nft_set.h | 90 +++++++
include/netlink/netfilter/nft_setelem.h | 63 +++++
lib/netfilter/nft_hash_expr.c | 307 ------------------------
lib/netfilter/nft_lookup_expr.c | 179 ++++++++++++++
lib/netfilter/nft_set.c | 321 +++++++++++++++++++++++++
lib/netfilter/nft_set_expr.c | 372 -----------------------------
lib/netfilter/nft_set_obj.c | 346 +++++++++++++++++++++++++++
lib/netfilter/nft_setelem.c | 391 +++++++++++++++++++++++++++++++
lib/netfilter/nft_setelem_obj.c | 215 +++++++++++++++++
src/.gitignore | 3 +
src/nf-set-add.c | 118 ++++++++++
src/nf-set-delete.c | 95 ++++++++
src/nf-set-dump.c | 96 ++++++++
src/nf-table-dump.c | 2 +-
17 files changed, 2271 insertions(+), 801 deletions(-)
create mode 100644 include/netlink/netfilter/nft_set.h
create mode 100644 include/netlink/netfilter/nft_setelem.h
delete mode 100644 lib/netfilter/nft_hash_expr.c
create mode 100644 lib/netfilter/nft_lookup_expr.c
create mode 100644 lib/netfilter/nft_set.c
delete mode 100644 lib/netfilter/nft_set_expr.c
create mode 100644 lib/netfilter/nft_set_obj.c
create mode 100644 lib/netfilter/nft_setelem.c
create mode 100644 lib/netfilter/nft_setelem_obj.c
create mode 100644 src/nf-set-add.c
create mode 100644 src/nf-set-delete.c
create mode 100644 src/nf-set-dump.c
Add support for the new set API to maintain sets independantly of the ruleset.
Signed-off-by: Patrick McHardy <kaber at trash.net>
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index 0309b9d..1c23073 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -11,6 +11,17 @@ enum nft_registers {
};
#define NFT_REG_MAX (__NFT_REG_MAX - 1)
+/**
+ * enum nft_verdicts - nf_tables internal verdicts
+ *
+ * @NFT_CONTINUE: continue evaluation of the current rule
+ * @NFT_BREAK: terminate evaluation of the current rule
+ * @NFT_JUMP: push the current chain on the jump stack and jump to a chain
+ * @NFT_GOTO: jump to a chain without pushing the current chain on the jump stack
+ * @NFT_RETURN: return to the topmost chain on the jump stack
+ *
+ * The nf_tables verdicts share their numeric space with the netfilter verdicts.
+ */
enum nft_verdicts {
NFT_CONTINUE = -1,
NFT_BREAK = -2,
@@ -29,9 +40,20 @@ enum nf_tables_msg_types {
NFT_MSG_NEWRULE,
NFT_MSG_GETRULE,
NFT_MSG_DELRULE,
+ NFT_MSG_NEWSET,
+ NFT_MSG_GETSET,
+ NFT_MSG_DELSET,
+ NFT_MSG_NEWSETELEM,
+ NFT_MSG_GETSETELEM,
+ NFT_MSG_DELSETELEM,
NFT_MSG_MAX,
};
+/**
+ * enum nft_list_attributes - nf_tables generic list netlink attributes
+ *
+ * @NFTA_LIST_ELEM: list element (NLA_NESTED)
+ */
enum nft_list_attributes {
NFTA_LIST_UNPEC,
NFTA_LIST_ELEM,
@@ -39,6 +61,12 @@ enum nft_list_attributes {
};
#define NFTA_LIST_MAX (__NFTA_LIST_MAX - 1)
+/**
+ * enum nft_hook_attributes - nf_tables netfilter hook netlink attributes
+ *
+ * @NFTA_HOOK_HOOKNUM: netfilter hook number (NLA_U32)
+ * @NFTA_HOOK_PRIORITY: netfilter hook priority (NLA_U32)
+ */
enum nft_hook_attributes {
NFTA_HOOK_UNSPEC,
NFTA_HOOK_HOOKNUM,
@@ -47,6 +75,11 @@ enum nft_hook_attributes {
};
#define NFTA_HOOK_MAX (__NFTA_HOOK_MAX - 1)
+/**
+ * enum nft_table_attributes - nf_tables table netlink attributes
+ *
+ * @NFTA_TABLE_NAME: name of the table (NLA_STRING)
+ */
enum nft_table_attributes {
NFTA_TABLE_UNSPEC,
NFTA_TABLE_NAME,
@@ -54,6 +87,13 @@ enum nft_table_attributes {
};
#define NFTA_TABLE_MAX (__NFTA_TABLE_MAX - 1)
+/**
+ * enum nft_chain_attributes - nf_tables chain netlink attributes
+ *
+ * @NFTA_CHAIN_TABLE: name of the table containing the chain (NLA_STRING)
+ * @NFTA_CHAIN_NAME: name of the chain (NLA_STRING)
+ * @NFTA_CHAIN_HOOK: hook specification for basechains (NLA_NESTED: nft_hook_attributes)
+ */
enum nft_chain_attributes {
NFTA_CHAIN_UNSPEC,
NFTA_CHAIN_TABLE,
@@ -63,6 +103,14 @@ enum nft_chain_attributes {
};
#define NFTA_CHAIN_MAX (__NFTA_CHAIN_MAX - 1)
+/**
+ * enum nft_rule_attributes - nf_tables rule netlink attributes
+ *
+ * @NFTA_RULE_TABLE: name of the table containing the rule (NLA_STRING)
+ * @NFTA_RULE_CHAIN: name of the chain containing the rule (NLA_STRING)
+ * @NFTA_RULE_HANDLE: numeric handle of the rule (NLA_U16)
+ * @NFTA_RULE_EXPRESSIONS: list of expressions (NLA_NESTED: nft_expr_attributes)
+ */
enum nft_rule_attributes {
NFTA_RULE_UNSPEC,
NFTA_RULE_TABLE,
@@ -73,6 +121,113 @@ enum nft_rule_attributes {
};
#define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1)
+/**
+ * enum nft_set_flags - nf_tables set flags
+ *
+ * @NFT_SET_ANONYMOUS: name allocation, automatic cleanup on unlink
+ * @NFT_SET_CONSTANT: set contents may not change while bound
+ * @NFT_SET_INTERVAL: set contains intervals
+ * @NFT_SET_MAP: set is used as a dictionary
+ */
+enum nft_set_flags {
+ NFT_SET_ANONYMOUS = 0x1,
+ NFT_SET_CONSTANT = 0x2,
+ NFT_SET_INTERVAL = 0x4,
+ NFT_SET_MAP = 0x8,
+};
+
+/**
+ * enum nft_set_attributes - nf_tables set netlink attributes
+ *
+ * @NFTA_SET_TABLE: table name (NLA_STRING)
+ * @NFTA_SET_NAME: set name (NLA_STRING)
+ * @NFTA_SET_FLAGS: bitmask of enum nft_set_flags (NLA_U32)
+ * @NFTA_SET_KEY_TYPE: key data type, informational purpose only (NLA_U32)
+ * @NFTA_SET_KEY_LEN: key data length (NLA_U32)
+ * @NFTA_SET_DATA_TYPE: mapping data type (NLA_U32)
+ * @NFTA_SET_DATA_LEN: mapping data length (NLA_U32)
+ */
+enum nft_set_attributes {
+ NFTA_SET_UNSPEC,
+ NFTA_SET_TABLE,
+ NFTA_SET_NAME,
+ NFTA_SET_FLAGS,
+ NFTA_SET_KEY_TYPE,
+ NFTA_SET_KEY_LEN,
+ NFTA_SET_DATA_TYPE,
+ NFTA_SET_DATA_LEN,
+ __NFTA_SET_MAX
+};
+#define NFTA_SET_MAX (__NFTA_SET_MAX - 1)
+
+/**
+ * enum nft_set_elem_flags - nf_tables set element flags
+ *
+ * @NFT_SET_ELEM_INTERVAL_END: element ends the previous interval
+ */
+enum nft_set_elem_flags {
+ NFT_SET_ELEM_INTERVAL_END = 0x1,
+};
+
+/**
+ * enum nft_set_elem_attributes - nf_tables set element netlink attributes
+ *
+ * @NFTA_SET_ELEM_KEY: key value (NLA_NESTED: nft_data)
+ * @NFTA_SET_ELEM_DATA: data value of mapping (NLA_NESTED: nft_data_attributes)
+ * @NFTA_SET_ELEM_FLAGS: bitmask of nft_set_elem_flags (NLA_U32)
+ */
+enum nft_set_elem_attributes {
+ NFTA_SET_ELEM_UNSPEC,
+ NFTA_SET_ELEM_KEY,
+ NFTA_SET_ELEM_DATA,
+ NFTA_SET_ELEM_FLAGS,
+ __NFTA_SET_ELEM_MAX
+};
+#define NFTA_SET_ELEM_MAX (__NFTA_SET_ELEM_MAX - 1)
+
+/**
+ * enum nft_set_elem_list_attributes - nf_tables set element list netlink attributes
+ *
+ * @NFTA_SET_ELEM_LIST_TABLE: table of the set to be changed (NLA_STRING)
+ * @NFTA_SET_ELEM_LIST_SET: name of the set to be changed (NLA_STRING)
+ * @NFTA_SET_ELEM_LIST_ELEMENTS: list of set elements (NLA_NESTED: nft_set_elem_attributes)
+ */
+enum nft_set_elem_list_attributes {
+ NFTA_SET_ELEM_LIST_UNSPEC,
+ NFTA_SET_ELEM_LIST_TABLE,
+ NFTA_SET_ELEM_LIST_SET,
+ NFTA_SET_ELEM_LIST_ELEMENTS,
+ __NFTA_SET_ELEM_LIST_MAX
+};
+#define NFTA_SET_ELEM_LIST_MAX (__NFTA_SET_ELEM_LIST_MAX - 1)
+
+/**
+ * enum nft_data_types - nf_tables data types
+ *
+ * @NFT_DATA_VALUE: generic data
+ * @NFT_DATA_VERDICT: netfilter verdict
+ *
+ * The type of data is usually determined by the kernel directly and is not
+ * explicitly specified by userspace. The only difference are sets, where
+ * userspace specifies the key and mapping data types.
+ *
+ * The values 0xffffff00-0xffffffff are reserved for internally used types.
+ * The remaining range can be freely used by userspace to encode types, all
+ * values are equivalent to NFT_DATA_VALUE.
+ */
+enum nft_data_types {
+ NFT_DATA_VALUE,
+ NFT_DATA_VERDICT = 0xffffff00U,
+};
+
+#define NFT_DATA_RESERVED_MASK 0xffffff00U
+
+/**
+ * enum nft_data_attributes - nf_tables data netlink attributes
+ *
+ * @NFTA_DATA_VALUE: generic data (NLA_BINARY)
+ * @NFTA_DATA_VERDICT: nf_tables verdict (NLA_NESTED: nft_verdict_attributes)
+ */
enum nft_data_attributes {
NFTA_DATA_UNSPEC,
NFTA_DATA_VALUE,
@@ -81,6 +236,12 @@ enum nft_data_attributes {
};
#define NFTA_DATA_MAX (__NFTA_DATA_MAX - 1)
+/**
+ * enum nft_verdict_attributes - nf_tables verdict netlink attributes
+ *
+ * @NFTA_VERDICT_CODE: nf_tables verdict (NLA_U32: enum nft_verdicts)
+ * @NFTA_VERDICT_CHAIN: jump target chain name (NLA_STRING)
+ */
enum nft_verdict_attributes {
NFTA_VERDICT_UNSPEC,
NFTA_VERDICT_CODE,
@@ -89,6 +250,12 @@ enum nft_verdict_attributes {
};
#define NFTA_VERDICT_MAX (__NFTA_VERDICT_MAX - 1)
+/**
+ * enum nft_expr_attributes - nf_tables expression netlink attributes
+ *
+ * @NFTA_EXPR_NAME: name of the expression type (NLA_STRING)
+ * @NFTA_EXPR_DATA: type specific data (NLA_NESTED)
+ */
enum nft_expr_attributes {
NFTA_EXPR_UNSPEC,
NFTA_EXPR_NAME,
@@ -97,6 +264,12 @@ enum nft_expr_attributes {
};
#define NFTA_EXPR_MAX (__NFTA_EXPR_MAX - 1)
+/**
+ * enum nft_immediate_attributes - nf_tables immediate expression netlink attributes
+ *
+ * @NFTA_IMMEDIATE_DREG: destination register to load data into (NLA_U32)
+ * @NFTA_IMMEDIATE_DATA: data to load (NLA_NESTED: nft_data_attributes)
+ */
enum nft_immediate_attributes {
NFTA_IMMEDIATE_UNSPEC,
NFTA_IMMEDIATE_DREG,
@@ -105,6 +278,27 @@ enum nft_immediate_attributes {
};
#define NFTA_IMMEDIATE_MAX (__NFTA_IMMEDIATE_MAX - 1)
+/**
+ * enum nft_bitwise_attributes - nf_tables bitwise expression netlink attributes
+ *
+ * @NFTA_BITWISE_SREG: source register (NLA_U32: nft_registers)
+ * @NFTA_BITWISE_DREG: destination register (NLA_U32: nft_registers)
+ * @NFTA_BITWISE_LEN: length of operands (NLA_U32)
+ * @NFTA_BITWISE_MASK: mask value (NLA_NESTED: nft_data_attributes)
+ * @NFTA_BITWISE_XOR: xor value (NLA_NESTED: nft_data_attributes)
+ *
+ * The bitwise expression performs the following operation:
+ *
+ * dreg = (sreg & mask) ^ xor
+ *
+ * which allow to express all bitwise operations:
+ *
+ * mask xor
+ * NOT: 1 1
+ * OR: 0 x
+ * XOR: 1 x
+ * AND: x 0
+ */
enum nft_bitwise_attributes {
NFTA_BITWISE_UNSPEC,
NFTA_BITWISE_SREG,
@@ -141,6 +335,13 @@ enum nft_cmp_ops {
NFT_CMP_GTE,
};
+/**
+ * enum nft_cmp_attributes - nf_tables cmp expression netlink attributes
+ *
+ * @NFTA_CMP_SREG: source register of data to compare (NLA_U32: nft_registers)
+ * @NFTA_CMP_OP: cmp operation (NLA_U32: nft_cmp_ops)
+ * @NFTA_CMP_DATA: data to compare against (NLA_NESTED: nft_data_attributes)
+ */
enum nft_cmp_attributes {
NFTA_CMP_UNSPEC,
NFTA_CMP_SREG,
@@ -150,65 +351,36 @@ enum nft_cmp_attributes {
};
#define NFTA_CMP_MAX (__NFTA_CMP_MAX - 1)
-enum nft_set_elem_flags {
- NFT_SE_INTERVAL_END = 0x1,
-};
-
-enum nft_set_elem_attributes {
- NFTA_SE_UNSPEC,
- NFTA_SE_KEY,
- NFTA_SE_DATA,
- NFTA_SE_FLAGS,
- __NFTA_SE_MAX
-};
-#define NFTA_SE_MAX (__NFTA_SE_MAX - 1)
-
-enum nft_set_flags {
- NFT_SET_INTERVAL = 0x1,
- NFT_SET_MAP = 0x2,
-};
-
-enum nft_set_attributes {
- NFTA_SET_UNSPEC,
- NFTA_SET_FLAGS,
- NFTA_SET_SREG,
- NFTA_SET_DREG,
- NFTA_SET_KLEN,
- NFTA_SET_DLEN,
- NFTA_SET_ELEMENTS,
- __NFTA_SET_MAX
-};
-#define NFTA_SET_MAX (__NFTA_SET_MAX - 1)
-
-enum nft_hash_flags {
- NFT_HASH_MAP = 0x1,
-};
-
-enum nft_hash_elem_attributes {
- NFTA_HE_UNSPEC,
- NFTA_HE_KEY,
- NFTA_HE_DATA,
- __NFTA_HE_MAX
-};
-#define NFTA_HE_MAX (__NFTA_HE_MAX - 1)
-
-enum nft_hash_attributes {
- NFTA_HASH_UNSPEC,
- NFTA_HASH_FLAGS,
- NFTA_HASH_SREG,
- NFTA_HASH_DREG,
- NFTA_HASH_KLEN,
- NFTA_HASH_ELEMENTS,
- __NFTA_HASH_MAX
-};
-#define NFTA_HASH_MAX (__NFTA_HASH_MAX - 1)
-
+enum nft_lookup_attributes {
+ NFTA_LOOKUP_UNSPEC,
+ NFTA_LOOKUP_SET,
+ NFTA_LOOKUP_SREG,
+ NFTA_LOOKUP_DREG,
+ __NFTA_LOOKUP_MAX
+};
+#define NFTA_LOOKUP_MAX (__NFTA_LOOKUP_MAX - 1)
+
+/**
+ * enum nft_payload_bases - nf_tables payload expression offset bases
+ *
+ * @NFT_PAYLOAD_LL_HEADER: link layer header
+ * @NFT_PAYLOAD_NETWORK_HEADER: network header
+ * @NFT_PAYLOAD_TRANSPORT_HEADER: transport header
+ */
enum nft_payload_bases {
NFT_PAYLOAD_LL_HEADER,
NFT_PAYLOAD_NETWORK_HEADER,
NFT_PAYLOAD_TRANSPORT_HEADER,
};
+/**
+ * enum nft_payload_attributes - nf_tables payload expression netlink attributes
+ *
+ * @NFTA_PAYLOAD_DREG: destination register to load data into (NLA_U32: nft_registers)
+ * @NFTA_PAYLOAD_BASE: payload base (NLA_U32: nft_payload_bases)
+ * @NFTA_PAYLOAD_OFFSET: payload offset relative to base (NLA_U32)
+ * @NFTA_PAYLOAD_LEN: payload length (NLA_U32)
+ */
enum nft_payload_attributes {
NFTA_PAYLOAD_UNSPEC,
NFTA_PAYLOAD_DREG,
@@ -229,6 +401,25 @@ enum nft_exthdr_attributes {
};
#define NFTA_EXTHDR_MAX (__NFTA_EXTHDR_MAX - 1)
+/**
+ * enum nft_meta_keys - nf_tables meta expression keys
+ *
+ * @NFT_META_LEN: packet length (skb->len)
+ * @NFT_META_PROTOCOL: packet ethertype protocol (skb->protocol), invalid in OUTPUT
+ * @NFT_META_PRIORITY: packet priority (skb->priority)
+ * @NFT_META_MARK: packet mark (skb->mark)
+ * @NFT_META_IIF: packet input interface index (dev->ifindex)
+ * @NFT_META_OIF: packet output interface index (dev->ifindex)
+ * @NFT_META_IIFNAME: packet input interface name (dev->name)
+ * @NFT_META_OIFNAME: packet output interface name (dev->name)
+ * @NFT_META_IIFTYPE: packet input interface type (dev->type)
+ * @NFT_META_OIFTYPE: packet output interface type (dev->type)
+ * @NFT_META_SKUID: originating socket UID (fsuid)
+ * @NFT_META_SKGID: originating socket GID (fsgid)
+ * @NFT_META_NFTRACE: packet nftrace bit
+ * @NFT_META_RTCLASSID: realm value of packet's route (skb->dst->tclassid)
+ * @NFT_META_SECMARK: packet secmark (skb->secmark)
+ */
enum nft_meta_keys {
NFT_META_LEN,
NFT_META_PROTOCOL,
@@ -247,6 +438,12 @@ enum nft_meta_keys {
NFT_META_SECMARK,
};
+/**
+ * enum nft_meta_attributes - nf_tables meta expression netlink attributes
+ *
+ * @NFTA_META_DREG: destination register (NLA_U32)
+ * @NFTA_META_KEY: meta data item to load (NLA_U32: nft_meta_keys)
+ */
enum nft_meta_attributes {
NFTA_META_UNSPEC,
NFTA_META_DREG,
@@ -255,6 +452,23 @@ enum nft_meta_attributes {
};
#define NFTA_META_MAX (__NFTA_META_MAX - 1)
+/**
+ * enum nft_ct_keys - nf_tables ct expression keys
+ *
+ * @NFT_CT_STATE: conntrack state (bitmask of enum ip_conntrack_info)
+ * @NFT_CT_DIRECTION: conntrack direction (enum ip_conntrack_dir)
+ * @NFT_CT_STATUS: conntrack status (bitmask of enum ip_conntrack_status)
+ * @NFT_CT_MARK: conntrack mark value
+ * @NFT_CT_SECMARK: conntrack secmark value
+ * @NFT_CT_EXPIRATION: relative conntrack expiration time in ms
+ * @NFT_CT_HELPER: connection tracking helper assigned to conntrack
+ * @NFT_CT_L3PROTOCOL: conntrack layer 3 protocol
+ * @NFT_CT_SRC: conntrack layer 3 protocol source (IPv4/IPv6 address)
+ * @NFT_CT_DST: conntrack layer 3 protocol destination (IPv4/IPv6 address)
+ * @NFT_CT_PROTOCOL: conntrack layer 4 protocol
+ * @NFT_CT_PROTO_SRC: conntrack layer 4 protocol source
+ * @NFT_CT_PROTO_DST: conntrack layer 4 protocol destination
+ */
enum nft_ct_keys {
NFT_CT_STATE,
NFT_CT_DIRECTION,
@@ -271,6 +485,13 @@ enum nft_ct_keys {
NFT_CT_PROTO_DST,
};
+/**
+ * enum nft_ct_attributes - nf_tables ct expression netlink attributes
+ *
+ * @NFTA_CT_DREG: destination register (NLA_U32)
+ * @NFTA_CT_KEY: conntrack data item to load (NLA_U32: nft_ct_keys)
+ * @NFTA_CT_DIRECTION: direction in case of directional keys (NLA_U8)
+ */
enum nft_ct_attributes {
NFTA_CT_UNSPEC,
NFTA_CT_DREG,
@@ -280,6 +501,12 @@ enum nft_ct_attributes {
};
#define NFTA_CT_MAX (__NFTA_CT_MAX - 1)
+/**
+ * enum nft_limit_attributes - nf_tables limit expression netlink attributes
+ *
+ * @NFTA_LIMIT_RATE: refill rate (NLA_U64)
+ * @NFTA_LIMIT_DEPTH: bucket depth (NLA_U64)
+ */
enum nft_limit_attributes {
NFTA_LIMIT_UNSPEC,
NFTA_LIMIT_RATE,
@@ -288,6 +515,12 @@ enum nft_limit_attributes {
};
#define NFTA_LIMIT_MAX (__NFTA_LIMIT_MAX - 1)
+/**
+ * enum nft_counter_attributes - nf_tables counter expression netlink attributes
+ *
+ * @NFTA_COUNTER_BYTES: number of bytes (NLA_U64)
+ * @NFTA_COUNTER_PACKETS: number of packets (NLA_U64)
+ */
enum nft_counter_attributes {
NFTA_COUNTER_UNSPEC,
NFTA_COUNTER_BYTES,
@@ -296,6 +529,14 @@ enum nft_counter_attributes {
};
#define NFTA_COUNTER_MAX (__NFTA_COUNTER_MAX - 1)
+/**
+ * enum nft_log_attributes - nf_tables log expression netlink attributes
+ *
+ * @NFTA_LOG_GROUP: netlink group to send messages to (NLA_U32)
+ * @NFTA_LOG_PREFIX: prefix to prepend to log messages (NLA_STRING)
+ * @NFTA_LOG_SNAPLEN: length of payload to include in netlink message (NLA_U32)
+ * @NFTA_LOG_QTHRESHOLD: queue threshold (NLA_U32)
+ */
enum nft_log_attributes {
NFTA_LOG_UNSPEC,
NFTA_LOG_GROUP,
@@ -306,11 +547,23 @@ enum nft_log_attributes {
};
#define NFTA_LOG_MAX (__NFTA_LOG_MAX - 1)
+/**
+ * enum nft_reject_types - nf_tables reject expression reject types
+ *
+ * @NFT_REJECT_ICMP_UNREACH: reject using ICMP unreachable
+ * @NFT_REJECT_TCP_RST: reject using TCP RST
+ */
enum nft_reject_types {
NFT_REJECT_ICMP_UNREACH,
NFT_REJECT_TCP_RST,
};
+/**
+ * enum nft_reject_attributes - nf_tables reject expression netlink attributes
+ *
+ * @NFTA_REJECT_TYPE: packet type to use (NLA_U32: nft_reject_types)
+ * @NFTA_REJECT_ICMP_CODE: ICMP code to use (NLA_U8)
+ */
enum nft_reject_attributes {
NFTA_REJECT_UNSPEC,
NFTA_REJECT_TYPE,
@@ -319,11 +572,26 @@ enum nft_reject_attributes {
};
#define NFTA_REJECT_MAX (__NFTA_REJECT_MAX - 1)
+/**
+ * enum nft_nat_types - nf_tables nat expression NAT types
+ *
+ * @NFT_NAT_SNAT: source NAT
+ * @NFT_NAT_DNAT: destination NAT
+ */
enum nft_nat_types {
NFT_NAT_SNAT,
NFT_NAT_DNAT,
};
+/**
+ * enum nft_nat_attributes - nf_tables nat expression netlink attributes
+ *
+ * @NFTA_NAT_TYPE: NAT type (NLA_U32: nft_nat_types)
+ * @NFTA_NAT_ADDR_MIN: source register of address range start (NLA_U32: nft_registers)
+ * @NFTA_NAT_ADDR_MAX: source register of address range end (NLA_U32: nft_registers)
+ * @NFTA_NAT_PROTO_MIN: source register of proto range start (NLA_U32: nft_registers)
+ * @NFTA_NAT_PROTO_MAX: source register of proto range end (NLA_U32: nft_registers)
+ */
enum nft_nat_attributes {
NFTA_NAT_UNSPEC,
NFTA_NAT_TYPE,
diff --git a/include/netlink-types.h b/include/netlink-types.h
index e8b637c..7ae0c3d 100644
--- a/include/netlink-types.h
+++ b/include/netlink-types.h
@@ -835,6 +835,28 @@ struct nfnl_nft_expr {
struct nl_list_head expr_list;
};
+struct nfnl_nft_set {
+ NLHDR_COMMON
+
+ uint8_t set_family;
+ struct nl_data *set_table;
+ struct nl_data *set_name;
+ uint32_t set_keytype;
+ uint8_t set_keylen;
+ uint32_t set_datatype;
+ uint8_t set_datalen;
+ uint32_t set_flags;
+};
+
+struct nfnl_nft_setelem {
+ NLHDR_COMMON
+
+ struct nl_list_head elem_list;
+ struct nfnl_nft_data *elem_key;
+ struct nfnl_nft_data *elem_data;
+ uint32_t elem_flags;
+};
+
struct nfnl_nft_data {
uint32_t d_type;
size_t d_size;
diff --git a/include/netlink/netfilter/nft_expr.h b/include/netlink/netfilter/nft_expr.h
index f6e2b53..b7895f0 100644
--- a/include/netlink/netfilter/nft_expr.h
+++ b/include/netlink/netfilter/nft_expr.h
@@ -84,74 +84,16 @@ extern struct nfnl_nft_data * nfnl_nft_cmp_get_data(const struct nfnl_nft_expr *
extern char * nfnl_nft_cmp_op2str(enum nft_cmp_ops, char *, size_t);
extern enum nft_cmp_ops nfnl_nft_cmp_str2op(const char *);
-extern int nfnl_nft_set_init(struct nfnl_nft_expr *);
-extern void nfnl_nft_set_set_flags(struct nfnl_nft_expr *,
- uint32_t);
-extern uint32_t nfnl_nft_set_get_flags(const struct nfnl_nft_expr *);
-extern void nfnl_nft_set_set_sreg(struct nfnl_nft_expr *,
- enum nft_registers);
-extern enum nft_registers nfnl_nft_set_get_sreg(const struct nfnl_nft_expr *);
-extern void nfnl_nft_set_set_dreg(struct nfnl_nft_expr *,
- enum nft_registers);
-extern enum nft_registers nfnl_nft_set_get_dreg(const struct nfnl_nft_expr *);
-extern void nfnl_nft_set_set_klen(struct nfnl_nft_expr *,
- unsigned int);
-extern unsigned int nfnl_nft_set_get_klen(const struct nfnl_nft_expr *);
-extern void nfnl_nft_set_set_dlen(struct nfnl_nft_expr *,
- unsigned int);
-extern unsigned int nfnl_nft_set_get_dlen(const struct nfnl_nft_expr *);
-
-extern int nfnl_nft_set_add_elem(struct nfnl_nft_expr *,
- struct nfnl_nft_data *,
- enum nft_set_elem_flags);
-extern int nfnl_nft_set_add_mapping(struct nfnl_nft_expr *,
- struct nfnl_nft_data *,
- struct nfnl_nft_data *,
- enum nft_set_elem_flags);
-extern void nfnl_nft_set_foreach_elem(const struct nfnl_nft_expr *,
- void (*)(struct nfnl_nft_data *,
- enum nft_set_elem_flags,
- void *),
- void *);
-extern void nfnl_nft_set_foreach_mapping(const struct nfnl_nft_expr *,
- void (*)(struct nfnl_nft_data *,
- struct nfnl_nft_data *,
- enum nft_set_elem_flags,
- void *),
- void *);
-extern char * nfnl_nft_set_flags2str(enum nft_set_flags,
- char *, size_t);
-extern enum nft_set_flags nfnl_nft_set_str2flags(const char *);
-
-
-extern int nfnl_nft_hash_init(struct nfnl_nft_expr *);
-extern void nfnl_nft_hash_set_flags(struct nfnl_nft_expr *,
- uint32_t);
-extern uint32_t nfnl_nft_hash_get_flags(const struct nfnl_nft_expr *);
-extern void nfnl_nft_hash_set_sreg(struct nfnl_nft_expr *,
- enum nft_registers);
-extern enum nft_registers nfnl_nft_hash_get_sreg(const struct nfnl_nft_expr *);
-extern void nfnl_nft_hash_set_dreg(struct nfnl_nft_expr *,
- enum nft_registers);
-extern enum nft_registers nfnl_nft_hash_get_dreg(const struct nfnl_nft_expr *);;
-extern void nfnl_nft_hash_set_klen(struct nfnl_nft_expr *,
- unsigned int);
-extern unsigned int nfnl_nft_hash_get_klen(const struct nfnl_nft_expr *);
-extern int nfnl_nft_hash_add_mapping(struct nfnl_nft_expr *,
- struct nfnl_nft_data *,
- struct nfnl_nft_data *);
-extern int nfnl_nft_hash_add_elem(struct nfnl_nft_expr *,
- struct nfnl_nft_data *);
-extern void nfnl_nft_hash_foreach_elem(const struct nfnl_nft_expr *,
- void (*)(struct nfnl_nft_data *,
- void *),
- void *);
-
-extern void nfnl_nft_hash_foreach_mapping(const struct nfnl_nft_expr *expr,
- void (*)(struct nfnl_nft_data *,
- struct nfnl_nft_data *,
- void *),
- void *);
+extern int nfnl_nft_lookup_init(struct nfnl_nft_expr *);
+extern void nfnl_nft_lookup_set_set(struct nfnl_nft_expr *,
+ const char *);
+extern const char * nfnl_nft_lookup_get_set(const struct nfnl_nft_expr *);
+extern void nfnl_nft_lookup_set_sreg(struct nfnl_nft_expr *,
+ enum nft_registers);
+extern enum nft_registers nfnl_nft_lookup_get_sreg(const struct nfnl_nft_expr *);
+extern void nfnl_nft_lookup_set_dreg(struct nfnl_nft_expr *,
+ enum nft_registers);
+extern enum nft_registers nfnl_nft_lookup_get_dreg(const struct nfnl_nft_expr *);
extern int nfnl_nft_meta_init(struct nfnl_nft_expr *);
extern void nfnl_nft_meta_set_dreg(struct nfnl_nft_expr *,
diff --git a/include/netlink/netfilter/nft_set.h b/include/netlink/netfilter/nft_set.h
new file mode 100644
index 0000000..dd4c03f
--- /dev/null
+++ b/include/netlink/netfilter/nft_set.h
@@ -0,0 +1,90 @@
+#ifndef NETLINK_NFT_SET_H_
+#define NETLINK_NFT_SET_H_
+
+#include <netlink/netlink.h>
+#include <netlink/addr.h>
+#include <netlink/cache.h>
+#include <netlink/msg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct nfnl_nft_set;
+enum nft_data_types;
+
+extern struct nl_object_ops nft_set_obj_ops;
+
+/* General */
+extern struct nfnl_nft_set * nfnl_nft_set_alloc(void);
+extern void nfnl_nft_set_get(struct nfnl_nft_set *);
+extern void nfnl_nft_set_put(struct nfnl_nft_set *);
+
+extern int nfnl_nft_set_alloc_cache(struct nl_sock *, int, const char *,
+ struct nl_cache **);
+
+extern int nfnlmsg_nft_set_group(struct nlmsghdr *);
+extern int nfnlmsg_nft_set_parse(struct nlmsghdr *,
+ struct nfnl_nft_set **);
+
+extern int nfnl_nft_set_dump_request(struct nl_sock *, int, const char *);
+
+extern int nfnl_nft_set_build_add_request(struct nfnl_nft_set *,
+ int, struct nl_msg **);
+extern int nfnl_nft_set_add(struct nl_sock *,
+ struct nfnl_nft_set *, int);
+
+extern int nfnl_nft_set_build_delete_request(struct nfnl_nft_set *,
+ int, struct nl_msg **);
+extern int nfnl_nft_set_delete(struct nl_sock *,
+ struct nfnl_nft_set *, int);
+
+extern int nfnl_nft_set_build_query_request(struct nfnl_nft_set *,
+ int, struct nl_msg **);
+extern int nfnl_nft_set_query(struct nl_sock *,
+ struct nfnl_nft_set *, int);
+
+extern void nfnl_nft_set_set_family(struct nfnl_nft_set *, uint8_t);
+extern int nfnl_nft_set_test_family(const struct nfnl_nft_set *);
+extern uint8_t nfnl_nft_set_get_family(const struct nfnl_nft_set *);
+
+extern int nfnl_nft_set_set_table(struct nfnl_nft_set *,
+ const char *, int);
+extern int nfnl_nft_set_test_table(const struct nfnl_nft_set *);
+extern const char * nfnl_nft_set_get_table(const struct nfnl_nft_set *);
+
+extern int nfnl_nft_set_set_name(struct nfnl_nft_set *,
+ const char *, int);
+extern int nfnl_nft_set_test_name(const struct nfnl_nft_set *);
+extern const char * nfnl_nft_set_get_name(const struct nfnl_nft_set *);
+
+extern void nfnl_nft_set_set_flags(struct nfnl_nft_set *, uint32_t);
+extern int nfnl_nft_set_test_flags(const struct nfnl_nft_set *);
+extern uint32_t nfnl_nft_set_get_flags(const struct nfnl_nft_set *);
+
+extern void nfnl_nft_set_set_keytype(struct nfnl_nft_set *,
+ enum nft_data_types);
+extern int nfnl_nft_set_test_keytype(const struct nfnl_nft_set *);
+extern enum nft_data_types nfnl_nft_set_get_keytype(const struct nfnl_nft_set *);
+
+extern void nfnl_nft_set_set_keylen(struct nfnl_nft_set *, uint32_t);
+extern int nfnl_nft_set_test_keylen(const struct nfnl_nft_set *);
+extern uint32_t nfnl_nft_set_get_keylen(const struct nfnl_nft_set *);
+
+extern void nfnl_nft_set_set_datatype(struct nfnl_nft_set *,
+ enum nft_data_types);
+extern int nfnl_nft_set_test_datatype(const struct nfnl_nft_set *);
+extern enum nft_data_types nfnl_nft_set_get_datatype(const struct nfnl_nft_set *);
+
+extern void nfnl_nft_set_set_datalen(struct nfnl_nft_set *, uint32_t);
+extern int nfnl_nft_set_test_datalen(const struct nfnl_nft_set *);
+extern uint32_t nfnl_nft_set_get_datalen(const struct nfnl_nft_set *);
+
+extern char * nfnl_nft_set_flags2str(uint32_t, char *, size_t);
+extern uint32_t nfnl_nft_set_str2flags(const char *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/netlink/netfilter/nft_setelem.h b/include/netlink/netfilter/nft_setelem.h
new file mode 100644
index 0000000..3e94b2c
--- /dev/null
+++ b/include/netlink/netfilter/nft_setelem.h
@@ -0,0 +1,63 @@
+#ifndef NETLINK_NFT_SETELEM_H_
+#define NETLINK_NFT_SETELEM_H_
+
+#include <netlink/netlink.h>
+#include <netlink/addr.h>
+#include <netlink/cache.h>
+#include <netlink/msg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct nfnl_nft_setelem;
+struct nfnl_nft_set;
+
+extern struct nl_object_ops nft_setelem_obj_ops;
+
+/* General */
+extern struct nfnl_nft_setelem *nfnl_nft_setelem_alloc(void);
+extern void nfnl_nft_setelem_get(struct nfnl_nft_setelem *);
+extern void nfnl_nft_setelem_put(struct nfnl_nft_setelem *);
+
+extern int nfnl_nft_setelem_alloc_cache(struct nl_sock *,
+ struct nfnl_nft_set *,
+ struct nl_cache **);
+
+extern int nfnl_nft_setelem_dump_request(struct nl_sock *,
+ struct nfnl_nft_set *);
+
+extern int nfnl_nft_setelem_add(struct nl_sock *,
+ struct nfnl_nft_set *,
+ struct nl_cache *, int);
+
+extern int nfnl_nft_setelem_delete(struct nl_sock *,
+ struct nfnl_nft_set *,
+ struct nl_cache *, int);
+
+extern int nfnl_nft_setelem_query(struct nl_sock *,
+ struct nfnl_nft_set *, int);
+
+extern void nfnl_nft_setelem_set_key(struct nfnl_nft_setelem *,
+ struct nfnl_nft_data *);
+extern int nfnl_nft_setelem_test_key(const struct nfnl_nft_setelem *);
+extern struct nfnl_nft_data * nfnl_nft_setelem_get_key(const struct nfnl_nft_setelem *);
+
+extern void nfnl_nft_setelem_set_data(struct nfnl_nft_setelem *,
+ struct nfnl_nft_data *);
+extern int nfnl_nft_setelem_test_data(const struct nfnl_nft_setelem *);
+extern struct nfnl_nft_data * nfnl_nft_setelem_get_data(const struct nfnl_nft_setelem *);
+
+extern void nfnl_nft_setelem_set_flags(struct nfnl_nft_setelem *,
+ uint32_t);
+extern int nfnl_nft_setelem_test_flags(const struct nfnl_nft_setelem *);
+extern uint32_t nfnl_nft_setelem_get_flags(const struct nfnl_nft_setelem *);
+
+extern char * nfnl_nft_setelem_flags2str(uint32_t, char *, size_t);
+extern uint32_t nfnl_nft_setelem_str2flags(const char *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/netfilter/nft_hash_expr.c b/lib/netfilter/nft_hash_expr.c
deleted file mode 100644
index 637f00e..0000000
--- a/lib/netfilter/nft_hash_expr.c
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * lib/netfilter/nft_hash_expr.c
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation version 2.1
- * of the License.
- *
- * Copyright (c) 2008 Patrick McHardy <kaber at trash.net>
- *
- * Development of this code funded by Astaro AG (http://www.astaro.com/)
- */
-
-#include <sys/types.h>
-#include <linux/netfilter/nf_tables.h>
-
-#include <netlink-local.h>
-#include <netlink/attr.h>
-#include <netlink/netfilter/nfnl.h>
-#include <netlink/netfilter/nft_data.h>
-#include <netlink/netfilter/nft_rule.h>
-#include <netlink/netfilter/nft_expr.h>
-#include <netlink/netfilter/nft-expr-modules.h>
-
-struct nft_hash_expr {
- struct nl_list_head hash_elements;
- enum nft_registers sreg;
- enum nft_registers dreg;
- uint32_t flags;
- uint32_t klen;
-};
-
-struct nft_hash_elem {
- struct nl_list_head list;
- struct nfnl_nft_data * key;
- struct nfnl_nft_data * data;
-};
-
-static struct nla_policy nft_hash_policy[NFTA_HASH_MAX + 1] = {
- [NFTA_HASH_FLAGS] = { .type = NLA_U32 },
- [NFTA_HASH_SREG] = { .type = NLA_U32 },
- [NFTA_HASH_DREG] = { .type = NLA_U32 },
- [NFTA_HASH_KLEN] = { .type = NLA_U32 },
- [NFTA_HASH_ELEMENTS] = { .type = NLA_NESTED },
-};
-
-static struct nla_policy nft_he_policy[NFTA_HE_MAX + 1] = {
- [NFTA_HE_KEY] = { .type = NLA_NESTED },
- [NFTA_HE_DATA] = { .type = NLA_NESTED },
-};
-
-static struct nft_expr_ops hash_expr_ops;
-
-static struct nft_hash_expr *nft_hash(const struct nfnl_nft_expr *expr)
-{
- return (struct nft_hash_expr *) expr->expr_data;
-}
-
-static struct nft_hash_expr *nft_hash_expr_alloc(struct nfnl_nft_expr *expr)
-{
- struct nft_hash_expr *hash;
-
- if (!expr->expr_data) {
- hash = calloc(1, sizeof(struct nft_hash_expr));
- if (hash) {
- nl_init_list_head(&hash->hash_elements);
- expr->expr_data = hash;
- expr->expr_ops = &hash_expr_ops;
- }
- }
-
- return nft_hash(expr);
-}
-
-static void nft_hash_free_data(struct nfnl_nft_expr *expr)
-{
- struct nft_hash_expr *hash = nft_hash(expr);
- struct nft_hash_elem *elem, *next;
-
- nl_list_for_each_entry_safe(elem, next, &hash->hash_elements, list) {
- nfnl_nft_data_free(elem->key);
- if (elem->data != NULL)
- nfnl_nft_data_free(elem->data);
- free(elem);
- }
-}
-
-static int nft_hash_msg_parser(struct nfnl_nft_expr *expr, struct nlattr *tb[])
-{
- struct nft_hash_expr *hash;
- struct nft_hash_elem *elem;
- struct nlattr *nla;
- struct nlattr *he[NFTA_HE_MAX + 1];
- int rem;
-
- hash = nft_hash_expr_alloc(expr);
- if (hash == NULL)
- return -ENOMEM;
-
- if (tb[NFTA_HASH_FLAGS] != NULL)
- hash->flags = ntohl(nla_get_u32(tb[NFTA_HASH_FLAGS]));
- if (tb[NFTA_HASH_SREG] != NULL)
- hash->sreg = ntohl(nla_get_u32(tb[NFTA_HASH_SREG]));
- if (tb[NFTA_HASH_DREG] != NULL)
- hash->dreg = ntohl(nla_get_u32(tb[NFTA_HASH_DREG]));
- if (tb[NFTA_HASH_KLEN] != NULL)
- hash->klen = ntohl(nla_get_u32(tb[NFTA_HASH_KLEN]));
-
- if (tb[NFTA_HASH_ELEMENTS] != NULL) {
- nla_for_each_nested(nla, tb[NFTA_HASH_ELEMENTS], rem) {
- if (nla_type(nla) != NFTA_LIST_ELEM)
- goto errout;
- if (nla_parse_nested(he, NFTA_HE_MAX, nla, nft_he_policy) < 0)
- goto errout;
-
- elem = malloc(sizeof(*elem));
- if (elem == NULL)
- goto errout;
- elem->data = NULL;
-
- if (he[NFTA_HE_KEY] == NULL)
- goto errout;
- if (nfnl_nft_data_parse(he[NFTA_HE_KEY], &elem->key) < 0)
- goto errout;
- if (he[NFTA_HE_DATA] != NULL) {
- if (nfnl_nft_data_parse(he[NFTA_HE_DATA], &elem->data) < 0)
- goto errout;
- }
- nl_list_add_tail(&elem->list, &hash->hash_elements);
- }
- }
-
- return 0;
-
-errout:
- return -1;
-}
-
-static int nft_hash_get_opts(struct nl_msg *msg, struct nfnl_nft_expr *expr)
-{
- struct nft_hash_expr *hash = nft_hash(expr);
- struct nft_hash_elem *elem;
- struct nlattr *list, *nest;
-
- if (nla_put_u32(msg, NFTA_HASH_FLAGS, htonl(hash->flags)) < 0)
- goto errout;
- if (nla_put_u32(msg, NFTA_HASH_SREG, htonl(hash->sreg)) < 0)
- goto errout;
- if (hash->flags & NFT_HASH_MAP &&
- nla_put_u32(msg, NFTA_HASH_DREG, htonl(hash->dreg)) < 0)
- goto errout;
- if (nla_put_u32(msg, NFTA_HASH_KLEN, htonl(hash->klen)) < 0)
- goto errout;
-
- list = nla_nest_start(msg, NFTA_HASH_ELEMENTS);
- if (list == NULL)
- goto errout;
- nl_list_for_each_entry(elem, &hash->hash_elements, list) {
- nest = nla_nest_start(msg, NFTA_LIST_ELEM);
- if (nest == NULL)
- goto errout;
- if (nfnl_nft_data_put(msg, NFTA_HE_KEY, elem->key) < 0)
- goto errout;
- if (hash->flags & NFT_HASH_MAP &&
- nfnl_nft_data_put(msg, NFTA_HE_DATA, elem->data) < 0)
- goto errout;
- nla_nest_end(msg, nest);
- }
- nla_nest_end(msg, list);
- return 0;
-
-errout:
- return -1;
-}
-
-static void nft_hash_dump(struct nfnl_nft_expr *expr, struct nl_dump_params *p)
-{
- struct nft_hash_expr *hash = nft_hash(expr);
- struct nft_hash_elem *elem;
- char *delim = "";
-
- if (hash->flags & NFT_HASH_MAP)
- nl_dump(p, "map reg %u load result reg %u\n",
- hash->sreg, hash->dreg);
- else
- nl_dump(p, "lookup reg %u\n", hash->sreg);
-
- delim = " { ";
- nl_list_for_each_entry(elem, &hash->hash_elements, list) {
- nl_dump(p, "%s", delim);
- nfnl_nft_data_dump(p, elem->key);
- if (elem->data) {
- nl_dump(p, " : ");
- nfnl_nft_data_dump(p, elem->data);
- }
- delim = ",\n ";
- }
- nl_dump(p, " }");
-}
-
-int nfnl_nft_hash_init(struct nfnl_nft_expr *expr)
-{
- if (nft_hash_expr_alloc(expr) == NULL)
- return -1;
- return 0;
-}
-
-void nfnl_nft_hash_set_flags(struct nfnl_nft_expr *expr, uint32_t flags)
-{
- nft_hash(expr)->flags = flags;
-}
-
-uint32_t nfnl_nft_hash_get_flags(const struct nfnl_nft_expr *expr)
-{
- return nft_hash(expr)->flags;
-}
-
-void nfnl_nft_hash_set_sreg(struct nfnl_nft_expr *expr, enum nft_registers reg)
-{
- nft_hash(expr)->sreg = reg;
-}
-
-enum nft_registers nfnl_nft_hash_get_sreg(const struct nfnl_nft_expr *expr)
-{
- return nft_hash(expr)->sreg;
-}
-
-void nfnl_nft_hash_set_dreg(struct nfnl_nft_expr *expr, enum nft_registers reg)
-{
- nft_hash(expr)->dreg = reg;
-}
-
-enum nft_registers nfnl_nft_hash_get_dreg(const struct nfnl_nft_expr *expr)
-{
- return nft_hash(expr)->dreg;
-}
-
-int nfnl_nft_hash_add_mapping(struct nfnl_nft_expr *expr,
- struct nfnl_nft_data *key,
- struct nfnl_nft_data *data)
-{
- struct nft_hash_expr *hash = nft_hash(expr);
- struct nft_hash_elem *elem;
-
- if (data != NULL && !(hash->flags & NFT_SET_MAP))
- return -1;
-
- elem = malloc(sizeof(*elem));
- if (elem == NULL)
- return -1;
-
- elem->key = key;
- elem->data = data;
- nl_list_add_tail(&elem->list, &hash->hash_elements);
- return 0;
-}
-
-int nfnl_nft_hash_add_elem(struct nfnl_nft_expr *expr, struct nfnl_nft_data *data)
-{
- return nfnl_nft_hash_add_mapping(expr, data, NULL);
-}
-
-void nfnl_nft_hash_foreach_elem(const struct nfnl_nft_expr *expr,
- void (*cb)(struct nfnl_nft_data *, void *),
- void *arg)
-{
- struct nft_hash_expr *hash = nft_hash(expr);
- struct nft_hash_elem *elem;
-
- nl_list_for_each_entry(elem, &hash->hash_elements, list)
- cb(elem->key, arg);
-}
-
-void nfnl_nft_hash_foreach_mapping(const struct nfnl_nft_expr *expr,
- void (*cb)(struct nfnl_nft_data *,
- struct nfnl_nft_data *, void *),
- void *arg)
-{
- struct nft_hash_expr *hash = nft_hash(expr);
- struct nft_hash_elem *elem;
-
- nl_list_for_each_entry(elem, &hash->hash_elements, list)
- cb(elem->key, elem->data, arg);
-}
-
-static struct nft_expr_ops hash_expr_ops = {
- .eo_name = "hash",
- .eo_dump[NL_DUMP_DETAILS] = nft_hash_dump,
- .eo_get_opts = nft_hash_get_opts,
- .eo_msg_parser = nft_hash_msg_parser,
- .eo_free_data = nft_hash_free_data,
- .eo_clone = NULL,
- .eo_policy = nft_hash_policy,
- .eo_maxattr = NFTA_HASH_MAX,
-};
-
-static void __init nft_hash_expr_init(void)
-{
- nft_expr_register(&hash_expr_ops);
-}
-
-static void __exit nft_hash_expr_exit(void)
-{
- nft_expr_unregister(&hash_expr_ops);
-}
-
-/** @} */
diff --git a/lib/netfilter/nft_lookup_expr.c b/lib/netfilter/nft_lookup_expr.c
new file mode 100644
index 0000000..45931dd
--- /dev/null
+++ b/lib/netfilter/nft_lookup_expr.c
@@ -0,0 +1,179 @@
+/*
+ * lib/netfilter/nft_lookup_expr.c
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2008-2009 Patrick McHardy <kaber at trash.net>
+ *
+ * Development of this code funded by Astaro AG (http://www.astaro.com/)
+ */
+
+#include <sys/types.h>
+#include <linux/netfilter/nf_tables.h>
+
+#include <netlink-local.h>
+#include <netlink/attr.h>
+#include <netlink/netfilter/nfnl.h>
+#include <netlink/netfilter/nft_data.h>
+#include <netlink/netfilter/nft_rule.h>
+#include <netlink/netfilter/nft_expr.h>
+#include <netlink/netfilter/nft-expr-modules.h>
+
+struct nft_lookup_expr {
+ char *set;
+ enum nft_registers sreg;
+ enum nft_registers dreg;
+};
+
+static struct nla_policy nft_lookup_policy[NFTA_LOOKUP_MAX + 1] = {
+ [NFTA_LOOKUP_SET] = { .type = NLA_STRING },
+ [NFTA_LOOKUP_SREG] = { .type = NLA_U32 },
+ [NFTA_LOOKUP_DREG] = { .type = NLA_U32 },
+};
+
+static struct nft_expr_ops lookup_expr_ops;
+
+static struct nft_lookup_expr *nft_lookup(const struct nfnl_nft_expr *expr)
+{
+ return (struct nft_lookup_expr *) expr->expr_data;
+}
+
+static struct nft_lookup_expr *nft_lookup_expr_alloc(struct nfnl_nft_expr *expr)
+{
+ struct nft_lookup_expr *lookup;
+
+ if (!expr->expr_data) {
+ lookup = calloc(1, sizeof(struct nft_lookup_expr));
+ if (lookup) {
+ memset(lookup, 0, sizeof(*lookup));
+ expr->expr_data = lookup;
+ expr->expr_ops = &lookup_expr_ops;
+ }
+ }
+
+ return nft_lookup(expr);
+}
+
+static void nft_lookup_free_data(struct nfnl_nft_expr *expr)
+{
+ struct nft_lookup_expr *lookup = nft_lookup(expr);
+
+ free(lookup->set);
+}
+
+static int nft_lookup_msg_parser(struct nfnl_nft_expr *expr, struct nlattr *tb[])
+{
+ struct nft_lookup_expr *lookup;
+
+ lookup = nft_lookup_expr_alloc(expr);
+ if (lookup == NULL)
+ goto err1;
+
+ if (tb[NFTA_LOOKUP_SET] != NULL) {
+ lookup->set = nla_strdup(tb[NFTA_LOOKUP_SET]);
+ if (lookup->set == NULL)
+ goto err2;
+ }
+ if (tb[NFTA_LOOKUP_SREG] != NULL)
+ lookup->sreg = ntohl(nla_get_u32(tb[NFTA_LOOKUP_SREG]));
+ if (tb[NFTA_LOOKUP_DREG] != NULL)
+ lookup->dreg = ntohl(nla_get_u32(tb[NFTA_LOOKUP_DREG]));
+
+ return 0;
+
+err2:
+ free(lookup);
+err1:
+ return ENOMEM;
+}
+
+static int nft_lookup_get_opts(struct nl_msg *msg, struct nfnl_nft_expr *expr)
+{
+ struct nft_lookup_expr *lookup = nft_lookup(expr);
+
+ if (nla_put_u32(msg, NFTA_LOOKUP_SREG, htonl(lookup->sreg)) < 0)
+ goto nla_put_failure;
+ if (lookup->set != NULL)
+ NLA_PUT_STRING(msg, NFTA_LOOKUP_SET, lookup->set);
+
+#if 0
+ if (lookup->flags & NFT_LOOKUP_MAP) {
+ if (nla_put_u32(msg, NFTA_LOOKUP_DREG, htonl(lookup->dreg)) < 0)
+ goto errout;
+ }
+#endif
+ return 0;
+
+nla_put_failure:
+ return -1;
+}
+
+static void nft_lookup_dump(struct nfnl_nft_expr *expr, struct nl_dump_params *p)
+{
+ struct nft_lookup_expr *lookup = nft_lookup(expr);
+
+ nl_dump(p, "reg %u set %s", lookup->sreg, lookup->set);
+}
+
+int nfnl_nft_lookup_init(struct nfnl_nft_expr *expr)
+{
+ if (nft_lookup_expr_alloc(expr) == NULL)
+ return -1;
+ return 0;
+}
+
+void nfnl_nft_lookup_set_set(struct nfnl_nft_expr *expr, const char *set)
+{
+ nft_lookup(expr)->set = strdup(set);
+}
+
+const char *nfnl_nft_lookup_get_set(const struct nfnl_nft_expr *expr)
+{
+ return nft_lookup(expr)->set;
+}
+
+void nfnl_nft_lookup_set_sreg(struct nfnl_nft_expr *expr, enum nft_registers reg)
+{
+ nft_lookup(expr)->sreg = reg;
+}
+
+enum nft_registers nfnl_nft_lookup_get_sreg(const struct nfnl_nft_expr *expr)
+{
+ return nft_lookup(expr)->sreg;
+}
+
+void nfnl_nft_lookup_set_dreg(struct nfnl_nft_expr *expr, enum nft_registers reg)
+{
+ nft_lookup(expr)->dreg = reg;
+}
+
+enum nft_registers nfnl_nft_lookup_get_dreg(const struct nfnl_nft_expr *expr)
+{
+ return nft_lookup(expr)->dreg;
+}
+
+static struct nft_expr_ops lookup_expr_ops = {
+ .eo_name = "lookup",
+ .eo_dump[NL_DUMP_DETAILS] = nft_lookup_dump,
+ .eo_get_opts = nft_lookup_get_opts,
+ .eo_msg_parser = nft_lookup_msg_parser,
+ .eo_free_data = nft_lookup_free_data,
+ .eo_clone = NULL,
+ .eo_policy = nft_lookup_policy,
+ .eo_maxattr = NFTA_LOOKUP_MAX,
+};
+
+static void __init nft_lookup_expr_init(void)
+{
+ nft_expr_register(&lookup_expr_ops);
+}
+
+static void __exit nft_lookup_expr_exit(void)
+{
+ nft_expr_unregister(&lookup_expr_ops);
+}
+
+/** @} */
diff --git a/lib/netfilter/nft_set.c b/lib/netfilter/nft_set.c
new file mode 100644
index 0000000..b3191b1
--- /dev/null
+++ b/lib/netfilter/nft_set.c
@@ -0,0 +1,321 @@
+/*
+ * lib/netfilter/nft_set.c nf_tables sets
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2009 Patrick McHardy <kaber at trash.net>
+ *
+ * Development of this code funded by Astaro AG (http://www.astaro.com/)
+ */
+
+/**
+ * @ingroup nfnl
+ * @defgroup nft nf_tables
+ * @brief
+ * @{
+ */
+
+#include <sys/types.h>
+#include <linux/netfilter/nf_tables.h>
+
+#include <netlink-local.h>
+#include <netlink/attr.h>
+#include <netlink/netfilter/nfnl.h>
+#include <netlink/netfilter/nft_set.h>
+
+static struct nl_cache_ops nfnl_nft_set_ops;
+
+static struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = {
+ [NFTA_SET_NAME] = { .type = NLA_STRING },
+ [NFTA_SET_FLAGS] = { .type = NLA_U32 },
+ [NFTA_SET_KEY_TYPE] = { .type = NLA_U32 },
+ [NFTA_SET_KEY_LEN] = { .type = NLA_U32 },
+ [NFTA_SET_DATA_TYPE] = { .type = NLA_U32 },
+ [NFTA_SET_DATA_LEN] = { .type = NLA_U32 },
+};
+
+int nfnlmsg_nft_set_parse(struct nlmsghdr *nlh, struct nfnl_nft_set **result)
+{
+ struct nfnl_nft_set *set;
+ struct nlattr *tb[NFTA_SET_MAX + 1], *nla;
+ int err;
+
+ set = nfnl_nft_set_alloc();
+ if (!set)
+ return -NLE_NOMEM;
+
+ set->ce_msgtype = nlh->nlmsg_type;
+
+ err = nlmsg_parse(nlh, sizeof(struct nfgenmsg), tb, NFTA_SET_MAX,
+ nft_set_policy);
+ if (err < 0)
+ goto errout;
+
+ nfnl_nft_set_set_family(set, nfnlmsg_family(nlh));
+
+ nla = tb[NFTA_SET_TABLE];
+ if (nla != NULL) {
+ err = nfnl_nft_set_set_table(set, nla_data(nla), nla_len(nla));
+ if (err < 0)
+ goto errout;
+ }
+
+ nla = tb[NFTA_SET_NAME];
+ if (nla != NULL) {
+ err = nfnl_nft_set_set_name(set, nla_data(nla), nla_len(nla));
+ if (err < 0)
+ goto errout;
+ }
+
+ if (tb[NFTA_SET_FLAGS] != NULL)
+ nfnl_nft_set_set_flags(set, ntohl(nla_get_u32(tb[NFTA_SET_FLAGS])));
+ if (tb[NFTA_SET_KEY_TYPE] != NULL)
+ nfnl_nft_set_set_keytype(set, ntohl(nla_get_u32(tb[NFTA_SET_KEY_TYPE])));
+ if (tb[NFTA_SET_KEY_LEN] != NULL)
+ nfnl_nft_set_set_keylen(set, ntohl(nla_get_u32(tb[NFTA_SET_KEY_LEN])));
+ if (tb[NFTA_SET_DATA_TYPE] != NULL)
+ nfnl_nft_set_set_datatype(set, ntohl(nla_get_u32(tb[NFTA_SET_DATA_TYPE])));
+ if (tb[NFTA_SET_DATA_LEN] != NULL)
+ nfnl_nft_set_set_datalen(set, ntohl(nla_get_u32(tb[NFTA_SET_DATA_LEN])));
+ *result = set;
+ return 0;
+
+errout:
+ nfnl_nft_set_put(set);
+ return err;
+}
+
+static int nft_set_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
+ struct nlmsghdr *nlh, struct nl_parser_param *pp)
+{
+ struct nfnl_nft_set *set;
+ int err;
+
+ err = nfnlmsg_nft_set_parse(nlh, &set);
+ if (err < 0)
+ goto errout;
+
+ err = pp->pp_cb((struct nl_object *) set, pp);
+
+errout:
+ nfnl_nft_set_put(set);
+ return err;
+}
+
+int nfnl_nft_set_dump_request(struct nl_sock *h, int family, const char *table)
+{
+ struct nl_msg *msg;
+
+ msg = nlmsg_alloc();
+ if (msg == NULL)
+ return -NLE_NOMEM;
+
+ if (nfnlmsg_put(msg, 0, 0, NFNL_SUBSYS_NFTABLES, NFT_MSG_GETSET,
+ NLM_F_DUMP, family, 0) < 0)
+ goto nla_put_failure;
+
+ if (table != NULL)
+ NLA_PUT_STRING(msg, NFTA_SET_TABLE, table);
+
+ return nl_send_auto_complete(h, msg);
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return -NLE_MSGSIZE;
+}
+
+static int nft_set_request_update(struct nl_cache *c, struct nl_sock *h)
+{
+ return nfnl_nft_set_dump_request(h, c->c_iarg1, (char *)c->c_iarg2);
+}
+
+static int nfnl_nft_set_build_message(struct nfnl_nft_set *set,
+ int cmd, int flags,
+ struct nl_msg **result)
+{
+ struct nl_msg *msg;
+
+ msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_NFTABLES, cmd, flags,
+ nfnl_nft_set_get_family(set), 0);
+ if (msg == NULL)
+ return -NLE_NOMEM;
+
+ if (nfnl_nft_set_test_table(set))
+ NLA_PUT_STRING(msg, NFTA_SET_TABLE, nfnl_nft_set_get_table(set));
+ if (nfnl_nft_set_test_name(set))
+ NLA_PUT_STRING(msg, NFTA_SET_NAME, nfnl_nft_set_get_name(set));
+ if (nfnl_nft_set_test_flags(set))
+ NLA_PUT_U32(msg, NFTA_SET_FLAGS, htonl(nfnl_nft_set_get_flags(set)));
+ if (nfnl_nft_set_test_keytype(set))
+ NLA_PUT_U32(msg, NFTA_SET_KEY_TYPE, htonl(nfnl_nft_set_get_keytype(set)));
+ if (nfnl_nft_set_test_keylen(set))
+ NLA_PUT_U32(msg, NFTA_SET_KEY_LEN, htonl(nfnl_nft_set_get_keylen(set)));
+ if (nfnl_nft_set_test_datatype(set))
+ NLA_PUT_U32(msg, NFTA_SET_DATA_TYPE, htonl(nfnl_nft_set_get_datatype(set)));
+ if (nfnl_nft_set_test_datalen(set))
+ NLA_PUT_U32(msg, NFTA_SET_DATA_LEN, htonl(nfnl_nft_set_get_datalen(set)));
+
+ *result = msg;
+ return 0;
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return -NLE_MSGSIZE;
+}
+
+int nfnl_nft_set_build_add_request(struct nfnl_nft_set *set, int flags,
+ struct nl_msg **result)
+{
+ return nfnl_nft_set_build_message(set, NFT_MSG_NEWSET,
+ NLM_F_CREATE | flags, result);
+}
+
+int nfnl_nft_set_add(struct nl_sock *h, struct nfnl_nft_set *set, int flags)
+{
+ struct nl_msg *msg;
+ int err;
+
+ err = nfnl_nft_set_build_add_request(set, flags, &msg);
+ if (err < 0)
+ return err;
+
+ err = nl_send_auto_complete(h, msg);
+ nlmsg_free(msg);
+ if (err < 0)
+ return err;
+
+ return wait_for_ack(h);
+}
+
+int nfnl_nft_set_build_delete_request(struct nfnl_nft_set *set, int flags,
+ struct nl_msg **result)
+{
+ return nfnl_nft_set_build_message(set, NFT_MSG_DELSET, flags, result);
+}
+
+int nfnl_nft_set_delete(struct nl_sock *h, struct nfnl_nft_set *set, int flags)
+{
+ struct nl_msg *msg;
+ int err;
+
+ err = nfnl_nft_set_build_delete_request(set, flags, &msg);
+ if (err < 0)
+ return err;
+
+ err = nl_send_auto_complete(h, msg);
+ nlmsg_free(msg);
+ if (err < 0)
+ return err;
+
+ return wait_for_ack(h);
+}
+
+int nfnl_nft_set_build_query_request(struct nfnl_nft_set *set, int flags,
+ struct nl_msg **result)
+{
+ return nfnl_nft_set_build_message(set, NFT_MSG_GETSET, flags, result);
+}
+
+int nfnl_nft_set_query(struct nl_sock *h, struct nfnl_nft_set *set, int flags)
+{
+ struct nl_msg *msg;
+ int err;
+
+ err = nfnl_nft_set_build_query_request(set, flags, &msg);
+ if (err < 0)
+ return err;
+
+ err = nl_send_auto_complete(h, msg);
+ nlmsg_free(msg);
+ if (err < 0)
+ return err;
+
+ return wait_for_ack(h);
+}
+
+/**
+ * @name Cache Management
+ * @{
+ */
+
+/**
+ * Build a set cache holding all nf_tables sets currently in the kernel
+ * @arg sock netlink sock
+ * @arg family address family
+ * @arg table table
+ * @arg result
+ *
+ * Allocates a new cache, initializes it properly and updates it to
+ * contain all sets currently in the specified table.
+ *
+ * @note The caller is responsible for destroying and freeing the
+ * cache after using it.
+ * @return The cache or NULL if an error has occured.
+ */
+int nfnl_nft_set_alloc_cache(struct nl_sock *sock, int family, const char *table,
+ struct nl_cache **result)
+{
+ struct nl_cache *cache;
+ int err;
+
+ cache = nl_cache_alloc(&nfnl_nft_set_ops);
+ if (!cache)
+ return -NLE_NOMEM;
+
+ cache->c_iarg1 = family;
+ cache->c_iarg2 = (unsigned long)table;
+
+ if (sock && (err = nl_cache_refill(sock, cache)) < 0) {
+ free(cache);
+ return err;
+ }
+
+ *result = cache;
+ return 0;
+}
+
+/** @} */
+
+/**
+ * @name Set Addition
+ * @{
+ */
+
+/** @} */
+
+static struct nl_af_group nft_set_groups[] = {
+ { AF_UNSPEC, NFNLGRP_NFTABLES },
+ { END_OF_GROUP_LIST },
+};
+
+#define NFNLMSG_NFT_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_NFTABLES, (type))
+static struct nl_cache_ops nfnl_nft_set_ops = {
+ .co_name = "netfilter/nft_set",
+ .co_hdrsize = NFNL_HDRLEN,
+ .co_msgtypes = {
+ { NFNLMSG_NFT_TYPE(NFT_MSG_NEWSET), NL_ACT_NEW, "new" },
+ { NFNLMSG_NFT_TYPE(NFT_MSG_GETSET), NL_ACT_GET, "get" },
+ { NFNLMSG_NFT_TYPE(NFT_MSG_DELSET), NL_ACT_DEL, "del" },
+ END_OF_MSGTYPES_LIST,
+ },
+ .co_protocol = NETLINK_NETFILTER,
+ .co_groups = nft_set_groups,
+ .co_request_update = nft_set_request_update,
+ .co_msg_parser = nft_set_msg_parser,
+ .co_obj_ops = &nft_set_obj_ops,
+};
+
+static void __init nft_set_init(void)
+{
+ nl_cache_mngt_register(&nfnl_nft_set_ops);
+}
+
+static void __exit nft_set_exit(void)
+{
+ nl_cache_mngt_unregister(&nfnl_nft_set_ops);
+}
+
+/** @} */
diff --git a/lib/netfilter/nft_set_expr.c b/lib/netfilter/nft_set_expr.c
deleted file mode 100644
index 5ee8c1f..0000000
--- a/lib/netfilter/nft_set_expr.c
+++ /dev/null
@@ -1,372 +0,0 @@
-/*
- * lib/netfilter/nft_set_expr.c
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation version 2.1
- * of the License.
- *
- * Copyright (c) 2008 Patrick McHardy <kaber at trash.net>
- *
- * Development of this code funded by Astaro AG (http://www.astaro.com/)
- */
-
-#include <sys/types.h>
-#include <linux/netfilter/nf_tables.h>
-
-#include <netlink-local.h>
-#include <netlink/attr.h>
-#include <netlink/netfilter/nfnl.h>
-#include <netlink/netfilter/nft_data.h>
-#include <netlink/netfilter/nft_rule.h>
-#include <netlink/netfilter/nft_expr.h>
-#include <netlink/netfilter/nft-expr-modules.h>
-
-struct nft_set_expr {
- struct nl_list_head set_elements;
- enum nft_registers sreg;
- enum nft_registers dreg;
- uint32_t flags;
- uint32_t klen;
- uint32_t dlen;
-};
-
-struct nft_set_elem {
- struct nl_list_head list;
- struct nfnl_nft_data * key;
- struct nfnl_nft_data * data;
- enum nft_set_elem_flags flags;
-};
-
-static struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = {
- [NFTA_SET_FLAGS] = { .type = NLA_U32 },
- [NFTA_SET_SREG] = { .type = NLA_U32 },
- [NFTA_SET_DREG] = { .type = NLA_U32 },
- [NFTA_SET_KLEN] = { .type = NLA_U32 },
- [NFTA_SET_DLEN] = { .type = NLA_U32 },
- [NFTA_SET_ELEMENTS] = { .type = NLA_NESTED },
-};
-
-static struct nla_policy nft_se_policy[NFTA_SE_MAX + 1] = {
- [NFTA_SE_KEY] = { .type = NLA_NESTED },
- [NFTA_SE_DATA] = { .type = NLA_NESTED },
- [NFTA_SE_FLAGS] = { .type = NLA_U32 },
-};
-
-static struct nft_expr_ops set_expr_ops;
-
-static struct nft_set_expr *nft_set(const struct nfnl_nft_expr *expr)
-{
- return (struct nft_set_expr *) expr->expr_data;
-}
-
-static struct nft_set_expr *nft_set_expr_alloc(struct nfnl_nft_expr *expr)
-{
- struct nft_set_expr *set;
-
- if (!expr->expr_data) {
- set = calloc(1, sizeof(struct nft_set_expr));
- if (set) {
- memset(set, 0, sizeof(*set));
- nl_init_list_head(&set->set_elements);
- expr->expr_data = set;
- expr->expr_ops = &set_expr_ops;
- }
- }
-
- return nft_set(expr);
-}
-
-static void nft_set_free_data(struct nfnl_nft_expr *expr)
-{
- struct nft_set_expr *set = nft_set(expr);
- struct nft_set_elem *elem, *next;
-
- nl_list_for_each_entry_safe(elem, next, &set->set_elements, list) {
- nfnl_nft_data_free(elem->key);
- if (elem->data != NULL)
- nfnl_nft_data_free(elem->data);
- free(elem);
- }
-}
-
-static int nft_set_msg_parser(struct nfnl_nft_expr *expr, struct nlattr *tb[])
-{
- struct nft_set_expr *set;
- struct nft_set_elem *elem;
- struct nlattr *nla;
- struct nlattr *se[NFTA_SE_MAX + 1];
- int rem;
-
- set = nft_set_expr_alloc(expr);
- if (set == NULL)
- return -ENOMEM;
-
- if (tb[NFTA_SET_FLAGS] != NULL)
- set->flags = ntohl(nla_get_u32(tb[NFTA_SET_FLAGS]));
- if (tb[NFTA_SET_SREG] != NULL)
- set->sreg = ntohl(nla_get_u32(tb[NFTA_SET_SREG]));
- if (tb[NFTA_SET_DREG] != NULL)
- set->dreg = ntohl(nla_get_u32(tb[NFTA_SET_DREG]));
- if (tb[NFTA_SET_KLEN] != NULL)
- set->klen = ntohl(nla_get_u32(tb[NFTA_SET_KLEN]));
- if (tb[NFTA_SET_DLEN] != NULL)
- set->dlen = ntohl(nla_get_u32(tb[NFTA_SET_DLEN]));
-
- if (tb[NFTA_SET_ELEMENTS] != NULL) {
- nla_for_each_nested(nla, tb[NFTA_SET_ELEMENTS], rem) {
- if (nla_type(nla) != NFTA_LIST_ELEM)
- goto errout;
- if (nla_parse_nested(se, NFTA_SE_MAX, nla, nft_se_policy) < 0)
- goto errout;
-
- elem = malloc(sizeof(*elem));
- if (elem == NULL)
- goto errout;
- memset(elem, 0, sizeof(*elem));
-
- if (se[NFTA_SE_KEY] == NULL)
- goto errout;
- if (nfnl_nft_data_parse(se[NFTA_SE_KEY], &elem->key) < 0)
- goto errout;
- if (se[NFTA_SE_DATA] != NULL) {
- if (nfnl_nft_data_parse(se[NFTA_SE_DATA], &elem->data) < 0)
- goto errout;
- }
- if (se[NFTA_SE_FLAGS] != NULL)
- elem->flags = ntohl(nla_get_u32(se[NFTA_SE_FLAGS]));
-
- nl_list_add_tail(&elem->list, &set->set_elements);
- }
- }
-
- return 0;
-
-errout:
- return -1;
-}
-
-static int nft_set_get_opts(struct nl_msg *msg, struct nfnl_nft_expr *expr)
-{
- struct nft_set_expr *set = nft_set(expr);
- struct nft_set_elem *elem;
- struct nlattr *list, *nest;
-
- if (nla_put_u32(msg, NFTA_SET_FLAGS, htonl(set->flags)) < 0)
- goto errout;
- if (nla_put_u32(msg, NFTA_SET_SREG, htonl(set->sreg)) < 0)
- goto errout;
- if (nla_put_u32(msg, NFTA_SET_KLEN, htonl(set->klen)) < 0)
- goto errout;
-
- if (set->flags & NFT_SET_MAP) {
- if (nla_put_u32(msg, NFTA_SET_DREG, htonl(set->dreg)) < 0)
- goto errout;
- if (nla_put_u32(msg, NFTA_SET_DLEN, htonl(set->dlen)) < 0)
- goto errout;
- }
-
- list = nla_nest_start(msg, NFTA_SET_ELEMENTS);
- if (list == NULL)
- goto errout;
- nl_list_for_each_entry(elem, &set->set_elements, list) {
- nest = nla_nest_start(msg, NFTA_LIST_ELEM);
- if (nest == NULL)
- goto errout;
- if (nfnl_nft_data_put(msg, NFTA_SE_KEY, elem->key) < 0)
- goto errout;
-
- if (set->flags & NFT_SET_MAP &&
- !(elem->flags & NFT_SE_INTERVAL_END) &&
- nfnl_nft_data_put(msg, NFTA_SE_DATA, elem->data) < 0)
- goto errout;
-
- if (elem->flags &&
- nla_put_u32(msg, NFTA_SE_FLAGS, htonl(elem->flags)) < 0)
- goto errout;
-
- nla_nest_end(msg, nest);
- }
- nla_nest_end(msg, list);
- return 0;
-
-errout:
- return -1;
-}
-
-static void nft_set_dump(struct nfnl_nft_expr *expr, struct nl_dump_params *p)
-{
- struct nft_set_expr *set = nft_set(expr);
- struct nft_set_elem *elem;
- char *delim;
-
- if (set->flags & NFT_SET_MAP)
- nl_dump(p, "map %s%ub/reg %u load %ub reg %u\n",
- set->flags & NFT_SET_INTERVAL ? "interval " : "",
- set->klen, set->sreg, set->dlen, set->dreg);
- else
- nl_dump(p, "lookup %s%ub/reg %u\n",
- set->flags & NFT_SET_INTERVAL ? "interval " : "",
- set->klen, set->sreg);
-
- delim = " { ";
- nl_list_for_each_entry(elem, &set->set_elements, list) {
- nl_dump(p, "%s", delim);
- nfnl_nft_data_dump(p, elem->key);
- if (elem->data) {
- nl_dump(p, " : ");
- nfnl_nft_data_dump(p, elem->data);
- } else if (elem->flags & NFT_SE_INTERVAL_END)
- nl_dump(p, "[end]");
- delim = ",\n ";
- }
- nl_dump(p, " }");
-}
-
-int nfnl_nft_set_init(struct nfnl_nft_expr *expr)
-{
- if (nft_set_expr_alloc(expr) == NULL)
- return -1;
- return 0;
-}
-
-void nfnl_nft_set_set_flags(struct nfnl_nft_expr *expr, uint32_t flags)
-{
- nft_set(expr)->flags |= flags;
-}
-
-uint32_t nfnl_nft_set_get_flags(const struct nfnl_nft_expr *expr)
-{
- return nft_set(expr)->flags;
-}
-
-void nfnl_nft_set_set_sreg(struct nfnl_nft_expr *expr, enum nft_registers reg)
-{
- nft_set(expr)->sreg = reg;
-}
-
-enum nft_registers nfnl_nft_set_get_sreg(const struct nfnl_nft_expr *expr)
-{
- return nft_set(expr)->sreg;
-}
-
-void nfnl_nft_set_set_dreg(struct nfnl_nft_expr *expr, enum nft_registers reg)
-{
- nft_set(expr)->dreg = reg;
-}
-
-enum nft_registers nfnl_nft_set_get_dreg(const struct nfnl_nft_expr *expr)
-{
- return nft_set(expr)->dreg;
-}
-
-void nfnl_nft_set_set_klen(struct nfnl_nft_expr *expr, unsigned int klen)
-{
- nft_set(expr)->klen = klen;
-}
-
-unsigned int nfnl_nft_set_get_klen(const struct nfnl_nft_expr *expr)
-{
- return nft_set(expr)->klen;
-}
-
-void nfnl_nft_set_set_dlen(struct nfnl_nft_expr *expr, unsigned int dlen)
-{
- nft_set(expr)->dlen = dlen;
-}
-
-unsigned int nfnl_nft_set_get_dlen(const struct nfnl_nft_expr *expr)
-{
- return nft_set(expr)->dlen;
-}
-
-int nfnl_nft_set_add_mapping(struct nfnl_nft_expr *expr,
- struct nfnl_nft_data *key,
- struct nfnl_nft_data *data,
- enum nft_set_elem_flags flags)
-{
- struct nft_set_expr *set = nft_set(expr);
- struct nft_set_elem *elem;
-
- if (data != NULL && !(set->flags & NFT_SET_MAP))
- return -1;
-
- elem = malloc(sizeof(*elem));
- if (elem == NULL)
- return -1;
-
- elem->key = key;
- elem->data = data;
- elem->flags = flags;
- nl_list_add_tail(&elem->list, &set->set_elements);
- return 0;
-}
-
-int nfnl_nft_set_add_elem(struct nfnl_nft_expr *expr, struct nfnl_nft_data *data,
- enum nft_set_elem_flags flags)
-{
- return nfnl_nft_set_add_mapping(expr, data, NULL, flags);
-}
-
-void nfnl_nft_set_foreach_elem(const struct nfnl_nft_expr *expr,
- void (*cb)(struct nfnl_nft_data *,
- enum nft_set_elem_flags, void *),
- void *arg)
-{
- struct nft_set_expr *set = nft_set(expr);
- struct nft_set_elem *elem;
-
- nl_list_for_each_entry(elem, &set->set_elements, list)
- cb(elem->key, elem->flags, arg);
-}
-
-void nfnl_nft_set_foreach_mapping(const struct nfnl_nft_expr *expr,
- void (*cb)(struct nfnl_nft_data *,
- struct nfnl_nft_data *,
- enum nft_set_elem_flags, void *),
- void *arg)
-{
- struct nft_set_expr *set = nft_set(expr);
- struct nft_set_elem *elem;
-
- nl_list_for_each_entry(elem, &set->set_elements, list)
- cb(elem->key, elem->data, elem->flags, arg);
-}
-
-static struct trans_tbl set_flags[] = {
- __ADD(NFT_SET_INTERVAL, interval)
- __ADD(NFT_SET_MAP, map)
-};
-
-char *nfnl_nft_set_flags2str(enum nft_set_flags flags, char *buf, size_t len)
-{
- return __flags2str(flags, buf, len, set_flags, ARRAY_SIZE(set_flags));
-}
-
-enum nft_set_flags nfnl_nft_set_str2flags(const char *name)
-{
- return __str2flags(name, set_flags, ARRAY_SIZE(set_flags));
-}
-
-static struct nft_expr_ops set_expr_ops = {
- .eo_name = "set",
- .eo_dump[NL_DUMP_DETAILS] = nft_set_dump,
- .eo_get_opts = nft_set_get_opts,
- .eo_msg_parser = nft_set_msg_parser,
- .eo_free_data = nft_set_free_data,
- .eo_clone = NULL,
- .eo_policy = nft_set_policy,
- .eo_maxattr = NFTA_SET_MAX,
-};
-
-static void __init nft_set_expr_init(void)
-{
- nft_expr_register(&set_expr_ops);
-}
-
-static void __exit nft_set_expr_exit(void)
-{
- nft_expr_unregister(&set_expr_ops);
-}
-
-/** @} */
diff --git a/lib/netfilter/nft_set_obj.c b/lib/netfilter/nft_set_obj.c
new file mode 100644
index 0000000..c74a469
--- /dev/null
+++ b/lib/netfilter/nft_set_obj.c
@@ -0,0 +1,346 @@
+/*
+ * lib/netfilter/nft_set_obj.c
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2008 Patrick McHardy <kaber at trash.net>
+ *
+ * Development of this code funded by Astaro AG (http://www.astaro.com/)
+ */
+
+#include <sys/types.h>
+#include <linux/netfilter/nf_tables.h>
+
+#include <netlink-local.h>
+#include <netlink/attr.h>
+#include <netlink/netfilter/nfnl.h>
+#include <netlink/netfilter/nft_table.h>
+#include <netlink/netfilter/nft_set.h>
+
+/** @cond SKIP */
+#define SET_ATTR_FAMILY (1UL << 0)
+#define SET_ATTR_TABLE (1UL << 1)
+#define SET_ATTR_NAME (1UL << 2)
+#define SET_ATTR_FLAGS (1UL << 3)
+#define SET_ATTR_KEYTYPE (1UL << 4)
+#define SET_ATTR_KEYLEN (1UL << 5)
+#define SET_ATTR_DATATYPE (1UL << 6)
+#define SET_ATTR_DATALEN (1UL << 7)
+/** @endcond */
+
+static void nft_set_free_data(struct nl_object *obj)
+{
+ struct nfnl_nft_set *set = nl_object_priv(obj);
+
+ if (set == NULL)
+ return;
+
+ nl_data_free(set->set_table);
+ nl_data_free(set->set_name);
+}
+
+static int nft_set_clone(struct nl_object *_dst, struct nl_object *_src)
+{
+ struct nfnl_nft_set *dst = nl_object_priv(_dst);
+ struct nfnl_nft_set *src = nl_object_priv(_src);
+ struct nl_data *table = NULL, *name = NULL;
+
+ if (src->set_table != NULL) {
+ table = nl_data_clone(src->set_table);
+ if (table == NULL)
+ goto err1;
+ }
+
+ if (src->set_name != NULL) {
+ name = nl_data_clone(src->set_name);
+ if (name == NULL)
+ goto err2;
+ }
+
+ dst->set_table = table;
+ dst->set_name = name;
+ return 0;
+
+err2:
+ nl_data_free(table);
+err1:
+ return -NLE_NOMEM;
+}
+
+static void nft_set_dump(struct nl_object *obj, struct nl_dump_params *p)
+{
+ struct nfnl_nft_set *set = nl_object_priv(obj);
+ char buf[64];
+
+ if (set->ce_mask & SET_ATTR_NAME) {
+ nl_dump(p, "%s %s",
+ set->set_flags & NFT_SET_MAP ? "map" : "set",
+ nfnl_nft_set_get_name(set));
+
+ if (set->ce_mask & SET_ATTR_TABLE)
+ nl_dump(p, "@%s/%s",
+ nfnl_nft_set_get_table(set),
+ nl_af2str(nfnl_nft_set_get_family(set),
+ buf, sizeof(buf)));
+
+ if (set->ce_mask & SET_ATTR_FLAGS) {
+ nfnl_nft_set_flags2str(set->set_flags, buf, sizeof(buf));
+ nl_dump(p, " <%s>", buf);
+ }
+
+ nl_dump(p, "\n");
+ }
+
+ if (set->ce_mask & (SET_ATTR_KEYTYPE | SET_ATTR_KEYLEN)) {
+ nl_dump(p, "\tkey: ");
+ if (set->ce_mask & SET_ATTR_KEYTYPE)
+ nl_dump(p, "type %x ", set->set_keytype);
+ if (set->ce_mask & SET_ATTR_KEYLEN)
+ nl_dump(p, "len %u ", set->set_keylen);
+ nl_dump(p, "\n");
+ }
+
+ if (set->ce_mask & (SET_ATTR_DATATYPE | SET_ATTR_DATALEN)) {
+ nl_dump(p, "\tdata: ");
+ if (set->ce_mask & SET_ATTR_DATATYPE)
+ nl_dump(p, "type %x ", set->set_datatype);
+ if (set->ce_mask & SET_ATTR_DATALEN)
+ nl_dump(p, "len %u ", set->set_datalen);
+ nl_dump(p, "\n");
+ }
+}
+
+static int nft_set_compare(struct nl_object *_a, struct nl_object *_b,
+ uint32_t attrs, int flags)
+{
+ // FIXME
+ return 0;
+}
+
+static struct trans_tbl nft_set_attrs[] = {
+ __ADD(SET_ATTR_FAMILY, family)
+ __ADD(SET_ATTR_TABLE, table)
+ __ADD(SET_ATTR_NAME, name)
+ __ADD(SET_ATTR_FLAGS, flags)
+ __ADD(SET_ATTR_KEYTYPE, keytype)
+ __ADD(SET_ATTR_KEYLEN, keylen)
+ __ADD(SET_ATTR_DATATYPE, datatype)
+ __ADD(SET_ATTR_DATALEN, datalen)
+};
+
+static char *nft_set_attrs2str(int attrs, char *buf, size_t len)
+{
+ return __flags2str(attrs, buf, len, nft_set_attrs,
+ ARRAY_SIZE(nft_set_attrs));
+}
+
+/**
+ * @name Allocation/Freeing
+ * @{
+ */
+
+struct nfnl_nft_set *nfnl_nft_set_alloc(void)
+{
+ return (struct nfnl_nft_set *) nl_object_alloc(&nft_set_obj_ops);
+}
+
+void nfnl_nft_set_get(struct nfnl_nft_set *set)
+{
+ nl_object_get((struct nl_object *) set);
+}
+
+void nfnl_nft_set_put(struct nfnl_nft_set *set)
+{
+ nl_object_put((struct nl_object *) set);
+}
+
+/** @} */
+
+/**
+ * @name Attributes
+ * @{
+ */
+
+void nfnl_nft_set_set_family(struct nfnl_nft_set *set, uint8_t family)
+{
+ set->set_family = family;
+ set->ce_mask |= SET_ATTR_FAMILY;
+}
+
+int nfnl_nft_set_test_family(const struct nfnl_nft_set *set)
+{
+ return !!(set->ce_mask & SET_ATTR_FAMILY);
+}
+
+uint8_t nfnl_nft_set_get_family(const struct nfnl_nft_set *set)
+{
+ return set->set_family;
+}
+
+int nfnl_nft_set_set_table(struct nfnl_nft_set *set, const char *table, int len)
+{
+ struct nl_data *data;
+
+ data = nl_data_alloc(table, len);
+ if (data == NULL)
+ return -NLE_NOMEM;
+
+ if (set->set_table)
+ nl_data_free(set->set_table);
+ set->set_table = data;
+ set->ce_mask |= SET_ATTR_TABLE;
+ return 0;
+}
+
+int nfnl_nft_set_test_table(const struct nfnl_nft_set *set)
+{
+ return !!(set->ce_mask & SET_ATTR_TABLE);
+}
+
+const char *nfnl_nft_set_get_table(const struct nfnl_nft_set *set)
+{
+ return nl_data_get(set->set_table);
+}
+
+int nfnl_nft_set_set_name(struct nfnl_nft_set *set, const char *name, int len)
+{
+ struct nl_data *data;
+
+ data = nl_data_alloc(name, len);
+ if (data == NULL)
+ return -NLE_NOMEM;
+
+ if (set->set_name)
+ nl_data_free(set->set_name);
+ set->set_name = data;
+ set->ce_mask |= SET_ATTR_NAME;
+ return 0;
+}
+
+int nfnl_nft_set_test_name(const struct nfnl_nft_set *set)
+{
+ return !!(set->ce_mask & SET_ATTR_NAME);
+}
+
+const char *nfnl_nft_set_get_name(const struct nfnl_nft_set *set)
+{
+ return nl_data_get(set->set_name);
+}
+
+void nfnl_nft_set_set_flags(struct nfnl_nft_set *set, uint32_t flags)
+{
+ set->set_flags |= flags;
+ set->ce_mask |= SET_ATTR_FLAGS;
+}
+
+int nfnl_nft_set_test_flags(const struct nfnl_nft_set *set)
+{
+ return !!(set->ce_mask & SET_ATTR_FLAGS);
+}
+
+uint32_t nfnl_nft_set_get_flags(const struct nfnl_nft_set *set)
+{
+ return set->set_flags;
+}
+
+void nfnl_nft_set_set_keytype(struct nfnl_nft_set *set, enum nft_data_types type)
+{
+ set->set_keytype = type;
+ set->ce_mask |= SET_ATTR_KEYTYPE;
+}
+
+int nfnl_nft_set_test_keytype(const struct nfnl_nft_set *set)
+{
+ return !!(set->ce_mask & SET_ATTR_KEYTYPE);
+}
+
+enum nft_data_types nfnl_nft_set_get_keytype(const struct nfnl_nft_set *set)
+{
+ return set->set_keytype;
+}
+
+void nfnl_nft_set_set_keylen(struct nfnl_nft_set *set, unsigned int len)
+{
+ set->set_keylen = len;
+ set->ce_mask |= SET_ATTR_KEYLEN;
+}
+
+int nfnl_nft_set_test_keylen(const struct nfnl_nft_set *set)
+{
+ return !!(set->ce_mask & SET_ATTR_KEYLEN);
+}
+
+unsigned int nfnl_nft_set_get_keylen(const struct nfnl_nft_set *set)
+{
+ return set->set_keylen;
+}
+
+void nfnl_nft_set_set_datatype(struct nfnl_nft_set *set, enum nft_data_types type)
+{
+ set->set_datatype = type;
+ set->ce_mask |= SET_ATTR_DATATYPE;
+}
+
+int nfnl_nft_set_test_datatype(const struct nfnl_nft_set *set)
+{
+ return !!(set->ce_mask & SET_ATTR_DATATYPE);
+}
+
+enum nft_data_types nfnl_nft_set_get_datatype(const struct nfnl_nft_set *set)
+{
+ return set->set_datatype;
+}
+
+void nfnl_nft_set_set_datalen(struct nfnl_nft_set *set, unsigned int len)
+{
+ set->set_datalen = len;
+ set->ce_mask |= SET_ATTR_DATALEN;
+}
+
+int nfnl_nft_set_test_datalen(const struct nfnl_nft_set *set)
+{
+ return !!(set->ce_mask & SET_ATTR_DATALEN);
+}
+
+unsigned int nfnl_nft_set_get_datalen(const struct nfnl_nft_set *set)
+{
+ return set->set_datalen;
+}
+
+static struct trans_tbl set_flags[] = {
+ __ADD(NFT_SET_ANONYMOUS, anonymous)
+ __ADD(NFT_SET_CONSTANT, constant)
+ __ADD(NFT_SET_INTERVAL, interval)
+ __ADD(NFT_SET_MAP, map)
+};
+
+char *nfnl_nft_set_flags2str(uint32_t flags, char *buf, size_t len)
+{
+ return __flags2str(flags, buf, len, set_flags, ARRAY_SIZE(set_flags));
+}
+
+uint32_t nfnl_nft_set_str2flags(const char *name)
+{
+ return __str2flags(name, set_flags, ARRAY_SIZE(set_flags));
+}
+
+/** @} */
+
+struct nl_object_ops nft_set_obj_ops = {
+ .oo_name = "netfilter/nft_set",
+ .oo_size = sizeof(struct nfnl_nft_set),
+ .oo_free_data = nft_set_free_data,
+ .oo_clone = nft_set_clone,
+ .oo_dump = {
+ [NL_DUMP_LINE] = nft_set_dump,
+ [NL_DUMP_DETAILS] = nft_set_dump,
+ [NL_DUMP_STATS] = nft_set_dump,
+ },
+ .oo_compare = nft_set_compare,
+ .oo_attrs2str = nft_set_attrs2str,
+};
+
+/** @} */
diff --git a/lib/netfilter/nft_setelem.c b/lib/netfilter/nft_setelem.c
new file mode 100644
index 0000000..f305005
--- /dev/null
+++ b/lib/netfilter/nft_setelem.c
@@ -0,0 +1,391 @@
+/*
+ * lib/netfilter/nft_setelem.c nf_tables set elements
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2009 Patrick McHardy <kaber at trash.net>
+ *
+ * Development of this code funded by Astaro AG (http://www.astaro.com/)
+ */
+
+/**
+ * @ingroup nfnl
+ * @defgroup nft nf_tables
+ * @brief
+ * @{
+ */
+
+#include <sys/types.h>
+#include <linux/netfilter/nf_tables.h>
+
+#include <netlink-local.h>
+#include <netlink/attr.h>
+#include <netlink/netfilter/nfnl.h>
+#include <netlink/netfilter/nft_set.h>
+#include <netlink/netfilter/nft_setelem.h>
+
+static struct nl_cache_ops nfnl_nft_setelem_ops;
+
+static struct nla_policy nft_set_elem_policy[NFTA_SET_ELEM_MAX + 1] = {
+ [NFTA_SET_ELEM_KEY] = { .type = NLA_NESTED },
+ [NFTA_SET_ELEM_DATA] = { .type = NLA_NESTED },
+ [NFTA_SET_ELEM_FLAGS] = { .type = NLA_U32 },
+};
+
+static struct nla_policy nft_set_elem_list_policy[NFTA_SET_ELEM_LIST_MAX + 1] = {
+ [NFTA_SET_ELEM_LIST_TABLE] = { .type = NLA_STRING },
+ [NFTA_SET_ELEM_LIST_SET] = { .type = NLA_STRING },
+ [NFTA_SET_ELEM_LIST_ELEMENTS] = { .type = NLA_NESTED },
+};
+
+static int nft_set_elem_parse(struct nlmsghdr *nlh, struct nlattr *nla,
+ struct nfnl_nft_setelem **result)
+{
+ struct nlattr *tb[NFTA_SET_ELEM_MAX + 1];
+ struct nfnl_nft_setelem *elem;
+ struct nfnl_nft_data *data;
+ uint32_t flags;
+ int err;
+
+ err = nla_parse_nested(tb, NFTA_SET_ELEM_MAX, nla, nft_set_elem_policy);
+ if (err < 0)
+ return err;
+
+ elem = nfnl_nft_setelem_alloc();
+ if (elem == NULL)
+ return -NLE_NOMEM;
+
+ elem->ce_msgtype = nlh->nlmsg_type;
+
+ if (tb[NFTA_SET_ELEM_KEY] != NULL) {
+ err = nfnl_nft_data_parse(tb[NFTA_SET_ELEM_KEY], &data);
+ if (err < 0)
+ goto err1;
+ nfnl_nft_setelem_set_key(elem, data);
+ }
+ if (tb[NFTA_SET_ELEM_DATA] != NULL) {
+ err = nfnl_nft_data_parse(tb[NFTA_SET_ELEM_DATA], &data);
+ if (err < 0)
+ goto err1;
+ nfnl_nft_setelem_set_data(elem, data);
+ }
+ if (tb[NFTA_SET_ELEM_FLAGS] != NULL) {
+ flags = ntohl(nla_get_u32(tb[NFTA_SET_ELEM_FLAGS]));
+ nfnl_nft_setelem_set_flags(elem, flags);
+ }
+
+ *result = elem;
+ return 0;
+
+err1:
+ nfnl_nft_setelem_put(elem);
+ return err;
+}
+
+static int nfnlmsg_nft_setelem_parse(struct nlmsghdr *nlh, struct nl_list_head *list)
+{
+ struct nlattr *tb[NFTA_SET_ELEM_LIST_MAX + 1], *nla;
+ struct nfnl_nft_setelem *elem;
+ int rem, err;
+
+ err = nlmsg_parse(nlh, sizeof(struct nfgenmsg), tb,
+ NFTA_SET_ELEM_LIST_MAX,
+ nft_set_elem_list_policy);
+ if (err < 0)
+ return err;
+
+ if (tb[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL)
+ goto err1;
+ nla_for_each_nested(nla, tb[NFTA_SET_ELEM_LIST_ELEMENTS], rem) {
+ err = nft_set_elem_parse(nlh, nla, &elem);
+ if (err < 0)
+ goto err1;
+ nl_list_add_tail(&elem->elem_list, list);
+ }
+ return 0;
+
+err1:
+ return err;
+}
+
+static int nft_setelem_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
+ struct nlmsghdr *nlh, struct nl_parser_param *pp)
+{
+ struct nfnl_nft_setelem *elem, *next;
+ NL_LIST_HEAD(list);
+ int err;
+
+ err = nfnlmsg_nft_setelem_parse(nlh, &list);
+
+ nl_list_for_each_entry_safe(elem, next, &list, elem_list) {
+ nl_list_del(&elem->elem_list);
+ if (err >= 0)
+ err = pp->pp_cb((struct nl_object *) elem, pp);
+ else
+ nfnl_nft_setelem_put(elem);
+ }
+
+ return err;
+}
+
+int nfnl_nft_setelem_dump_request(struct nl_sock *h, struct nfnl_nft_set *set)
+{
+ struct nl_msg *msg;
+
+ msg = nlmsg_alloc();
+ if (msg == NULL)
+ return -NLE_NOMEM;
+
+ if (nfnlmsg_put(msg, 0, 0, NFNL_SUBSYS_NFTABLES, NFT_MSG_GETSETELEM,
+ NLM_F_DUMP, set->set_family, 0) < 0)
+ goto nla_put_failure;
+
+ if (nfnl_nft_set_test_table(set))
+ NLA_PUT_STRING(msg, NFTA_SET_ELEM_LIST_TABLE,
+ nfnl_nft_set_get_table(set));
+ if (nfnl_nft_set_test_name(set))
+ NLA_PUT_STRING(msg, NFTA_SET_ELEM_LIST_SET,
+ nfnl_nft_set_get_name(set));
+
+ return nl_send_auto_complete(h, msg);
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return -NLE_MSGSIZE;
+}
+
+static int nft_setelem_request_update(struct nl_cache *c, struct nl_sock *h)
+{
+ return nfnl_nft_setelem_dump_request(h, (struct nfnl_nft_set *)c->c_iarg1);
+}
+
+static int nfnl_nft_setelem_build(struct nl_msg *msg,
+ const struct nfnl_nft_setelem *elem)
+{
+ unsigned int size = msg->nm_size;
+ struct nlattr *nest;
+ int err;
+
+ nest = nla_nest_start(msg, NFTA_LIST_ELEM);
+ if (nest == NULL)
+ goto nla_put_failure;
+
+ if (elem->elem_key != NULL) {
+ err = nfnl_nft_data_put(msg, NFTA_SET_ELEM_KEY, elem->elem_key);
+ if (err < 0)
+ goto nla_put_failure;
+ }
+ if (elem->elem_data != NULL) {
+ err = nfnl_nft_data_put(msg, NFTA_SET_ELEM_DATA, elem->elem_data);
+ if (err < 0)
+ goto nla_put_failure;
+ }
+ if (elem->elem_flags != 0)
+ NLA_PUT_U32(msg, NFTA_SET_ELEM_FLAGS, htonl(elem->elem_flags));
+
+ nla_nest_end(msg, nest);
+ return 0;
+
+nla_put_failure:
+ msg->nm_size = size;
+ return -NLE_MSGSIZE;
+}
+
+static int nfnl_nft_setelem_build_message(struct nfnl_nft_set *set,
+ struct nl_cache *elements,
+ struct nl_object **last,
+ int cmd, int flags,
+ struct nl_msg **result)
+{
+ struct nl_object *obj;
+ struct nlattr *nest;
+ struct nl_msg *msg;
+
+ obj = last != NULL ? *last : NULL;
+ obj = nl_list_prepare_entry(obj, &elements->c_items, ce_list);
+ if (obj->ce_list.next == &elements->c_items)
+ return 0;
+
+ msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_NFTABLES, cmd, flags,
+ nfnl_nft_set_get_family(set), 0);
+ if (msg == NULL)
+ return -NLE_NOMEM;
+
+ if (nfnl_nft_set_test_table(set))
+ NLA_PUT_STRING(msg, NFTA_SET_ELEM_LIST_TABLE,
+ nfnl_nft_set_get_table(set));
+ if (nfnl_nft_set_test_name(set))
+ NLA_PUT_STRING(msg, NFTA_SET_ELEM_LIST_SET,
+ nfnl_nft_set_get_name(set));
+
+ nest = nla_nest_start(msg, NFTA_SET_ELEM_LIST_ELEMENTS);
+ if (nest == NULL)
+ goto nla_put_failure;
+
+ nl_list_for_each_entry_continue(obj, &elements->c_items, ce_list) {
+ if (nfnl_nft_setelem_build(msg, nl_object_priv(obj)) < 0)
+ break;
+ if (last != NULL)
+ *last = obj;
+ }
+ nla_nest_end(msg, nest);
+
+ *result = msg;
+ return msg->nm_size;
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return -NLE_MSGSIZE;
+}
+
+static int nfnl_nft_setelem_send_messages(struct nl_sock *h,
+ struct nfnl_nft_set *set,
+ struct nl_cache *elements,
+ int cmd, int flags)
+{
+ struct nl_object *obj = NULL;
+ struct nl_msg *msg;
+ int err;
+
+ while (1) {
+ err = nfnl_nft_setelem_build_message(set, elements, &obj,
+ cmd, flags, &msg);
+ if (err <= 0)
+ break;
+
+ err = nl_send_auto_complete(h, msg);
+ nlmsg_free(msg);
+ if (err < 0)
+ break;
+ err = wait_for_ack(h);
+ if (err < 0)
+ break;
+ }
+ return err;
+}
+
+int nfnl_nft_setelem_add(struct nl_sock *h, struct nfnl_nft_set *set,
+ struct nl_cache *elements, int flags)
+{
+ return nfnl_nft_setelem_send_messages(h, set, elements,
+ NFT_MSG_NEWSETELEM,
+ NLM_F_CREATE | flags);
+}
+
+int nfnl_nft_setelem_build_delete_request(struct nfnl_nft_set *set, int flags,
+ struct nl_msg **result)
+{
+ return nfnl_nft_setelem_build_message(set, NULL, NULL, NFT_MSG_DELSETELEM,
+ flags, result);
+}
+
+int nfnl_nft_setelem_delete(struct nl_sock *h, struct nfnl_nft_set *set,
+ struct nl_cache *elements, int flags)
+{
+ return nfnl_nft_setelem_send_messages(h, set, elements,
+ NFT_MSG_DELSETELEM,
+ flags);
+}
+
+int nfnl_nft_setelem_build_query_request(struct nfnl_nft_set *set, int flags,
+ struct nl_msg **result)
+{
+ return nfnl_nft_setelem_build_message(set, NULL, NULL, NFT_MSG_GETSETELEM,
+ flags, result);
+}
+
+int nfnl_nft_setelem_query(struct nl_sock *h, struct nfnl_nft_set *set, int flags)
+{
+ struct nl_msg *msg;
+ int err;
+
+ err = nfnl_nft_set_build_query_request(set, flags, &msg);
+ if (err < 0)
+ return err;
+
+ err = nl_send_auto_complete(h, msg);
+ nlmsg_free(msg);
+ if (err < 0)
+ return err;
+
+ return wait_for_ack(h);
+}
+
+/**
+ * @name Cache Management
+ * @{
+ */
+
+/**
+ * Build a set cache holding all nf_tables sets currently in the kernel
+ * @arg sock netlink sock
+ * @arg set nftables set
+ * @arg result
+ *
+ * Allocates a new cache, initializes it properly and updates it to
+ * contain all elements currently in the specified set.
+ *
+ * @note The caller is responsible for destroying and freeing the
+ * cache after using it.
+ * @return The cache or NULL if an error has occured.
+ */
+int nfnl_nft_setelem_alloc_cache(struct nl_sock *sock, struct nfnl_nft_set *set,
+ struct nl_cache **result)
+{
+ struct nl_cache *cache;
+ int err;
+
+ cache = nl_cache_alloc(&nfnl_nft_setelem_ops);
+ if (!cache)
+ return -NLE_NOMEM;
+
+ cache->c_iarg1 = (unsigned long)set;
+
+ if (sock && (err = nl_cache_refill(sock, cache)) < 0) {
+ free(cache);
+ return err;
+ }
+
+ *result = cache;
+ return 0;
+}
+
+/** @} */
+
+/**
+ * @name Set Element Addition
+ * @{
+ */
+
+/** @} */
+
+#define NFNLMSG_NFT_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_NFTABLES, (type))
+static struct nl_cache_ops nfnl_nft_setelem_ops = {
+ .co_name = "netfilter/nft_setelem",
+ .co_hdrsize = NFNL_HDRLEN,
+ .co_msgtypes = {
+ { NFNLMSG_NFT_TYPE(NFT_MSG_NEWSETELEM), NL_ACT_NEW, "new" },
+ { NFNLMSG_NFT_TYPE(NFT_MSG_GETSETELEM), NL_ACT_GET, "get" },
+ { NFNLMSG_NFT_TYPE(NFT_MSG_DELSETELEM), NL_ACT_DEL, "del" },
+ END_OF_MSGTYPES_LIST,
+ },
+ .co_protocol = NETLINK_NETFILTER,
+ .co_request_update = nft_setelem_request_update,
+ .co_msg_parser = nft_setelem_msg_parser,
+ .co_obj_ops = &nft_setelem_obj_ops,
+};
+
+static void __init nft_setelem_init(void)
+{
+ nl_cache_mngt_register(&nfnl_nft_setelem_ops);
+}
+
+static void __exit nft_setelem_exit(void)
+{
+ nl_cache_mngt_unregister(&nfnl_nft_setelem_ops);
+}
+
+/** @} */
diff --git a/lib/netfilter/nft_setelem_obj.c b/lib/netfilter/nft_setelem_obj.c
new file mode 100644
index 0000000..8c754cc
--- /dev/null
+++ b/lib/netfilter/nft_setelem_obj.c
@@ -0,0 +1,215 @@
+/*
+ * lib/netfilter/nft_setelem_obj.c
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2008 Patrick McHardy <kaber at trash.net>
+ *
+ * Development of this code funded by Astaro AG (http://www.astaro.com/)
+ */
+
+#include <sys/types.h>
+#include <linux/netfilter/nf_tables.h>
+
+#include <netlink-local.h>
+#include <netlink/attr.h>
+#include <netlink/netfilter/nfnl.h>
+#include <netlink/netfilter/nft_table.h>
+#include <netlink/netfilter/nft_set.h>
+#include <netlink/netfilter/nft_setelem.h>
+
+/** @cond SKIP */
+#define SETELEM_ATTR_KEY (1UL << 0)
+#define SETELEM_ATTR_DATA (1UL << 1)
+#define SETELEM_ATTR_FLAGS (1UL << 2)
+/** @endcond */
+
+static void nft_setelem_free_data(struct nl_object *obj)
+{
+ struct nfnl_nft_setelem *elem = nl_object_priv(obj);;
+
+ if (elem == NULL)
+ return;
+
+ if (elem->elem_key != NULL)
+ nfnl_nft_data_free(elem->elem_key);
+ if (elem->elem_data != NULL)
+ nfnl_nft_data_free(elem->elem_data);
+}
+
+static int nft_setelem_clone(struct nl_object *_dst, struct nl_object *_src)
+{
+ struct nfnl_nft_set *dst = nl_object_priv(_dst);
+ struct nfnl_nft_set *src = nl_object_priv(_src);
+ struct nl_data *table = NULL, *name = NULL;
+
+ if (src->set_table != NULL) {
+ table = nl_data_clone(src->set_table);
+ if (table == NULL)
+ goto err1;
+ }
+
+ if (src->set_name != NULL) {
+ name = nl_data_clone(src->set_name);
+ if (name == NULL)
+ goto err2;
+ }
+
+ dst->set_table = table;
+ dst->set_name = name;
+
+err2:
+ nl_data_free(table);
+err1:
+ return -NLE_NOMEM;
+}
+
+static void nft_setelem_dump(struct nl_object *obj, struct nl_dump_params *p)
+{
+ struct nfnl_nft_setelem *elem = nl_object_priv(obj);
+
+ nl_dump(p, "element ");
+ if (elem->ce_mask & SETELEM_ATTR_KEY)
+ nfnl_nft_data_dump(p, elem->elem_key);
+ if (elem->ce_mask & SETELEM_ATTR_DATA) {
+ nl_dump(p, " : ");
+ nfnl_nft_data_dump(p, elem->elem_data);
+ }
+ if (elem->ce_mask & SETELEM_ATTR_FLAGS) {
+ if (elem->elem_flags & NFT_SET_ELEM_INTERVAL_END)
+ nl_dump(p, "[end]");
+ }
+ nl_dump(p, "\n");
+}
+
+static int nft_setelem_compare(struct nl_object *_a, struct nl_object *_b,
+ uint32_t attrs, int flags)
+{
+ // FIXME
+ return 0;
+}
+
+static struct trans_tbl nft_setelem_attrs[] = {
+ __ADD(SETELEM_ATTR_KEY, key)
+ __ADD(SETELEM_ATTR_DATA, data)
+ __ADD(SETELEM_ATTR_FLAGS, flags)
+};
+
+static char *nft_setelem_attrs2str(int attrs, char *buf, size_t len)
+{
+ return __flags2str(attrs, buf, len, nft_setelem_attrs,
+ ARRAY_SIZE(nft_setelem_attrs));
+}
+
+/**
+ * @name Allocation/Freeing
+ * @{
+ */
+
+struct nfnl_nft_setelem *nfnl_nft_setelem_alloc(void)
+{
+ return (struct nfnl_nft_setelem *) nl_object_alloc(&nft_setelem_obj_ops);
+}
+
+void nfnl_nft_setelem_get(struct nfnl_nft_setelem *elem)
+{
+ nl_object_get((struct nl_object *) elem);
+}
+
+void nfnl_nft_setelem_put(struct nfnl_nft_setelem *elem)
+{
+ nl_object_put((struct nl_object *) elem);
+}
+
+/** @} */
+
+/**
+ * @name Attributes
+ * @{
+ */
+
+void nfnl_nft_setelem_set_key(struct nfnl_nft_setelem *elem,
+ struct nfnl_nft_data *key)
+{
+ elem->elem_key = key;
+ elem->ce_mask |= SETELEM_ATTR_KEY;
+}
+
+int nfnl_nft_setelem_test_key(const struct nfnl_nft_setelem *elem)
+{
+ return !!(elem->ce_mask & SETELEM_ATTR_KEY);
+}
+
+struct nfnl_nft_data *nfnl_nft_setelem_get_key(const struct nfnl_nft_setelem *elem)
+{
+ return elem->elem_key;
+}
+
+void nfnl_nft_setelem_set_data(struct nfnl_nft_setelem *elem,
+ struct nfnl_nft_data *data)
+{
+ elem->elem_data = data;
+ elem->ce_mask |= SETELEM_ATTR_DATA;
+}
+
+int nfnl_nft_setelem_test_data(const struct nfnl_nft_setelem *elem)
+{
+ return !!(elem->ce_mask & SETELEM_ATTR_DATA);
+}
+
+struct nfnl_nft_data *nfnl_nft_setelem_get_data(const struct nfnl_nft_setelem *elem)
+{
+ return elem->elem_data;
+}
+
+void nfnl_nft_setelem_set_flags(struct nfnl_nft_setelem *elem, uint32_t flags)
+{
+ elem->elem_flags |= flags;
+ elem->ce_mask |= SETELEM_ATTR_FLAGS;
+}
+
+int nfnl_nft_setelem_test_flags(const struct nfnl_nft_setelem *elem)
+{
+ return !!(elem->ce_mask & SETELEM_ATTR_FLAGS);
+}
+
+uint32_t nfnl_nft_setelem_get_flags(const struct nfnl_nft_setelem *elem)
+{
+ return elem->elem_flags;
+}
+
+static struct trans_tbl setelem_flags[] = {
+ __ADD(NFT_SET_ELEM_INTERVAL_END, interval_end)
+};
+
+char *nfnl_nft_setelem_flags2str(uint32_t flags, char *buf, size_t len)
+{
+ return __flags2str(flags, buf, len, setelem_flags,
+ ARRAY_SIZE(setelem_flags));
+}
+
+uint32_t nfnl_nft_setelem_str2flags(const char *name)
+{
+ return __str2flags(name, setelem_flags, ARRAY_SIZE(setelem_flags));
+}
+
+/** @} */
+
+struct nl_object_ops nft_setelem_obj_ops = {
+ .oo_name = "netfilter/nft_setelem",
+ .oo_size = sizeof(struct nfnl_nft_setelem),
+ .oo_free_data = nft_setelem_free_data,
+ .oo_clone = nft_setelem_clone,
+ .oo_dump = {
+ [NL_DUMP_LINE] = nft_setelem_dump,
+ [NL_DUMP_DETAILS] = nft_setelem_dump,
+ [NL_DUMP_STATS] = nft_setelem_dump,
+ },
+ .oo_compare = nft_setelem_compare,
+ .oo_attrs2str = nft_setelem_attrs2str,
+};
+
+/** @} */
diff --git a/src/.gitignore b/src/.gitignore
index b292567..3afc312 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -38,3 +38,6 @@ nf-rule-dump
nf-table-add
nf-table-del
nf-table-dump
+nf-set-add
+nf-set-delete
+nf-set-dump
diff --git a/src/nf-set-add.c b/src/nf-set-add.c
new file mode 100644
index 0000000..499ad89
--- /dev/null
+++ b/src/nf-set-add.c
@@ -0,0 +1,118 @@
+/*
+ * src/nf-set-add.c Add nf_tables set
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2009 Patrick McHardy <kaber at trash.net>
+ *
+ * Development of this code funded by Astaro AG (http://www.astaro.com/)
+ */
+
+#include "utils.h"
+#include <netlink-local.h>
+
+#include <linux/netfilter/nf_tables.h>
+#include <netlink/netfilter/netfilter.h>
+#include <netlink/netfilter/nft_set.h>
+#include <netlink/netfilter/nft_expr.h>
+#include <linux/ip.h>
+
+static void print_usage(void)
+{
+ printf(
+ "Usage: nf-set-add --family <family> --table <table> --name <name> [ options ]\n"
+ " options := { --keytype type | --keylen len | --flags flags | \n"
+ " --datatype type | --datalen len }\n"
+ );
+ exit(1);
+}
+
+int main(int argc, char *argv[])
+{
+ struct nl_sock *nf_sock;
+ struct nfnl_nft_set *set;
+ int err = 1;
+
+ struct nl_dump_params params = {
+ .dp_fd = stdout,
+ .dp_type = NL_DUMP_DETAILS,
+ };
+
+ nf_sock = nlt_alloc_socket();
+ if (nlt_connect(nf_sock, NETLINK_NETFILTER) < 0)
+ return -1;
+
+ set = nfnl_nft_set_alloc();
+ if (set == NULL)
+ goto errout;
+
+ for (;;) {
+ int c, optidx = 0;
+ enum {
+ ARG_FAMILY = 257,
+ ARG_TABLE,
+ ARG_NAME,
+ ARG_KEYTYPE,
+ ARG_KEYLEN,
+ ARG_FLAGS,
+ ARG_DATATYPE,
+ ARG_DATALEN,
+ };
+ static struct option long_opts[] = {
+ { "help", 0, 0, 'h' },
+ { "family", 1, 0, ARG_FAMILY, },
+ { "table", 1, 0, ARG_TABLE, },
+ { "name", 1, 0, ARG_NAME, },
+ { "keytype", 1, 0, ARG_KEYTYPE },
+ { "keylen", 1, 0, ARG_KEYLEN, },
+ };
+
+ c = getopt_long(argc, argv, "hf:t:n:k:", long_opts, &optidx);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ print_usage();
+ exit(0);
+ case ARG_FAMILY:
+ nfnl_nft_set_set_family(set, nl_str2af(optarg));
+ break;
+ case ARG_TABLE:
+ nfnl_nft_set_set_table(set, optarg, strlen(optarg) + 1);
+ break;
+ case ARG_NAME:
+ nfnl_nft_set_set_name(set, optarg, strlen(optarg) + 1);
+ break;
+ case ARG_KEYTYPE:
+ nfnl_nft_set_set_keytype(set, strtoul(optarg, NULL, 0));
+ break;
+ case ARG_KEYLEN:
+ nfnl_nft_set_set_keylen(set, strtoul(optarg, NULL, 0));
+ break;
+ case ARG_FLAGS:
+ nfnl_nft_set_set_flags(set, nfnl_nft_set_str2flags(optarg));
+ case ARG_DATATYPE:
+ nfnl_nft_set_set_datatype(set, strtoul(optarg, NULL, 0));
+ break;
+ case ARG_DATALEN:
+ nfnl_nft_set_set_datalen(set, strtoul(optarg, NULL, 0));
+ break;
+ }
+ }
+
+ nl_object_dump((struct nl_object *) set, ¶ms);
+ err = nfnl_nft_set_add(nf_sock, set, NLM_F_EXCL);
+ if (err < 0)
+ fprintf(stderr, "Unable to add set: %s\n",
+ nl_geterror(err));
+ else
+ err = 0;
+
+ nfnl_nft_set_put(set);
+errout:
+ return err;
+}
diff --git a/src/nf-set-delete.c b/src/nf-set-delete.c
new file mode 100644
index 0000000..749a57c
--- /dev/null
+++ b/src/nf-set-delete.c
@@ -0,0 +1,95 @@
+/*
+ * src/nf-set-add.c Delete nf_tables set
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2009 Patrick McHardy <kaber at trash.net>
+ *
+ * Development of this code funded by Astaro AG (http://www.astaro.com/)
+ */
+
+#include "utils.h"
+#include <netlink-local.h>
+
+#include <linux/netfilter/nf_tables.h>
+#include <netlink/netfilter/netfilter.h>
+#include <netlink/netfilter/nft_set.h>
+#include <netlink/netfilter/nft_expr.h>
+#include <linux/ip.h>
+
+static void print_usage(void)
+{
+ printf(
+ "Usage: nf-set-delete --family <family> --table <table> --name <name>\n"
+ );
+ exit(1);
+}
+
+int main(int argc, char *argv[])
+{
+ struct nl_sock *nf_sock;
+ struct nfnl_nft_set *set;
+ int err = 1;
+
+ struct nl_dump_params params = {
+ .dp_fd = stdout,
+ .dp_type = NL_DUMP_DETAILS,
+ };
+
+ nf_sock = nlt_alloc_socket();
+ if (nlt_connect(nf_sock, NETLINK_NETFILTER) < 0)
+ return -1;
+
+ set = nfnl_nft_set_alloc();
+ if (set == NULL)
+ goto errout;
+
+ for (;;) {
+ int c, optidx = 0;
+ enum {
+ ARG_FAMILY = 257,
+ ARG_TABLE,
+ ARG_NAME,
+ };
+ static struct option long_opts[] = {
+ { "help", 0, 0, 'h' },
+ { "family", 1, 0, ARG_FAMILY, },
+ { "table", 1, 0, ARG_TABLE, },
+ { "name", 1, 0, ARG_NAME, },
+ };
+
+ c = getopt_long(argc, argv, "hf:t:n:k:", long_opts, &optidx);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ print_usage();
+ exit(0);
+ case ARG_FAMILY:
+ nfnl_nft_set_set_family(set, nl_str2af(optarg));
+ break;
+ case ARG_TABLE:
+ nfnl_nft_set_set_table(set, optarg, strlen(optarg) + 1);
+ break;
+ case ARG_NAME:
+ nfnl_nft_set_set_name(set, optarg, strlen(optarg) + 1);
+ break;
+ }
+ }
+
+ nl_object_dump((struct nl_object *) set, ¶ms);
+ err = nfnl_nft_set_delete(nf_sock, set, 0);
+ if (err < 0)
+ fprintf(stderr, "Unable to delete set: %s\n",
+ nl_geterror(err));
+ else
+ err = 0;
+
+ nfnl_nft_set_put(set);
+errout:
+ return err;
+}
diff --git a/src/nf-set-dump.c b/src/nf-set-dump.c
new file mode 100644
index 0000000..62de6fb
--- /dev/null
+++ b/src/nf-set-dump.c
@@ -0,0 +1,96 @@
+/*
+ * src/nf-set-dump.c Dump nf_tables set attributes
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2009 Patrick McHardy <kaber at trash.net>
+ *
+ * Development of this code funded by Astaro AG (http://www.astaro.com/)
+ */
+
+#include "utils.h"
+#include <netlink/netfilter/nft_set.h>
+
+static void print_usage(void)
+{
+ printf(
+ "Usage: nf-set-dump --family <family> --table <table> <mode>\n"
+ " mode := { brief | detailed | stats | xml }\n"
+ );
+ exit(1);
+}
+
+int main(int argc, char *argv[])
+{
+ struct nl_sock *nf_sock;
+ struct nl_cache *set_cache;
+ struct nl_dump_params params = {
+ .dp_fd = stdout,
+ .dp_type = NL_DUMP_LINE,
+ };
+ int err = 1, family = AF_UNSPEC;
+ const char *table = NULL;
+
+ for (;;) {
+ int c, optidx = 0;
+ enum {
+ ARG_FAMILY = 257,
+ ARG_TABLE,
+ };
+ static struct option long_opts[] = {
+ { "help", 0, 0, 'h' },
+ { "family", 1, 0, ARG_FAMILY, },
+ { "table", 1, 0, ARG_TABLE, },
+ };
+
+ c = getopt_long(argc, argv, "hf:t:", long_opts, &optidx);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ print_usage();
+ break;
+ case ARG_FAMILY:
+ family = nl_str2af(optarg);
+ break;
+ case ARG_TABLE:
+ table = optarg;
+ break;
+ }
+ }
+
+ if (optind == argc) {
+ print_usage();
+ exit(1);
+ }
+ params.dp_type = nlt_parse_dumptype(argv[optind]);
+ if (params.dp_type < 0)
+ goto errout_cache;
+
+
+ nf_sock = nlt_alloc_socket();
+
+ if (nlt_connect(nf_sock, NETLINK_NETFILTER) < 0)
+ return -1;
+
+ err = nfnl_nft_set_alloc_cache(nf_sock, family, table, &set_cache);
+ if (err < 0) {
+ fprintf(stderr, "Unable to retrieve set cache: %s\n",
+ nl_geterror(err));
+ goto errout;
+ }
+ nl_cache_mngt_provide(set_cache);
+
+ nl_cache_dump(set_cache, ¶ms);
+
+ err = 0;
+
+errout_cache:
+ nl_cache_free(set_cache);
+errout:
+ return err;
+}
diff --git a/src/nf-table-dump.c b/src/nf-table-dump.c
index f2d4fdc..84430ca 100644
--- a/src/nf-table-dump.c
+++ b/src/nf-table-dump.c
@@ -17,7 +17,7 @@
static void print_usage(void)
{
printf(
- "Usage: nf-ct-dump <mode>\n"
+ "Usage: nf-table-dump <mode>\n"
" mode := { brief | detailed | stats | xml }\n"
);
exit(1);
More information about the netfilter-cvslog
mailing list