Compare commits

...

10 Commits

Author SHA1 Message Date
Phil Sutter 148198ec34 ipset-7.11-8.el9 2023-05-18 13:38:47 +00:00
Phil Sutter 248a4faa27 Add rpminspec.yaml
Use of gethostbyname2 is deliberate and thus safe.
2022-12-07 19:27:49 +01:00
Phil Sutter 54a680f4c5 ipset-7.11-7.el9
- Fix for bad performance restoring large sets which are in use

Resolves: rhbz#2043008
2022-01-31 16:47:07 +01:00
Phil Sutter ab9d7d6766 ipset-7.11-6.el9
- Sync ipset.service with RHEL8, fix the required package name

Resolves: rhbz#2007320
2021-11-08 17:27:32 +01:00
Mohan Boddu 8930afa6b2 Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
Related: rhbz#1991688
Signed-off-by: Mohan Boddu <mboddu@redhat.com>
2021-08-09 20:59:13 +00:00
Aleksandra Fedorova 77095e9ed5 Add RHEL gating configuration 2021-07-15 03:11:21 +02:00
Phil Sutter c24fda81bb ipset-7.11-4.el9
- Improve deprecation notice a bit

Related: rhbz#1945190
2021-07-02 18:10:17 +02:00
Phil Sutter 2d3ca2a6c9 ipset-7.11-3.el9
- Add deprecation notice to ipset.8

Resolves: rhbz#1945190
2021-06-25 13:50:27 +02:00
Mohan Boddu f591b2f352 - Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
Signed-off-by: Mohan Boddu <mboddu@redhat.com>
2021-04-16 00:36:52 +00:00
DistroBaker eb831320d1 Merged update from upstream sources
This is an automated DistroBaker update from upstream sources.
If you do not know what this is about or would like to opt out,
contact the OSCI team.

Source: https://src.fedoraproject.org/rpms/ipset.git#522137356f2f27d0e817b406bd140893c4f86cc8
2021-03-21 09:35:33 +00:00
20 changed files with 1993 additions and 211 deletions

1
.ipset.metadata Normal file
View File

@ -0,0 +1 @@
a10e4e8f0ed2fa540b653d987a93069c0c276f61 ipset-7.11.tar.bz2

View File

@ -0,0 +1,48 @@
From e9398b721855f8fbfb30a21d475d0aeb7f85bbe5 Mon Sep 17 00:00:00 2001
From: Phil Sutter <psutter@redhat.com>
Date: Fri, 25 Jun 2021 13:47:57 +0200
Subject: [PATCH] Add deprecation notice to ipset.8
This is RHEL9 trying to friendly kick people towards nftables.
---
src/ipset.8 | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/src/ipset.8 b/src/ipset.8
index 97cece9fb04b5..d68e9bbc22891 100644
--- a/src/ipset.8
+++ b/src/ipset.8
@@ -51,6 +51,18 @@ COMMANDS := { \fBcreate\fR | \fBadd\fR | \fBdel\fR | \fBtest\fR | \fBdestroy\fR
.PP
\fBipset\fR \fB\-\fR
.SH "DESCRIPTION"
+This tool is
+.B deprecated
+in Red Hat Enterprise Linux. It is maintenance only and will not receive new
+features. New setups should use
+.BR nft (8).
+Existing setups should migrate to
+.BR nft (8)
+when possible. See
+.UR https://red.ht/nft_your_tables
+.UE
+for details.
+.PP
\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)
@@ -1099,8 +1111,9 @@ Bugs? No, just funny features. :\-)
OK, just kidding...
.SH "SEE ALSO"
\fBiptables\fR(8),
-\fBip6tables\fR(8)
-\fBiptables-extensions\fR(8)
+\fBip6tables\fR(8),
+\fBiptables-extensions\fR(8),
+\fBnft\fR(8)
.SH "AUTHORS"
Jozsef Kadlecsik wrote ipset, which is based on ippool by
Joakim Axelsson, Patrick Schaaf and Martin Josefsson.
--
2.31.1

View File

@ -1,28 +0,0 @@
From 39fde1381f0ba9101f65c08f2abda5426a46f8b1 Mon Sep 17 00:00:00 2001
From: Jan Engelhardt <jengelh@inai.de>
Date: Mon, 22 Jan 2018 22:50:33 +0100
Subject: [PATCH] build: do install libipset/args.h
libipset/types.h includes args.h, therefore args.h must be installed
too.
Signed-off-by: Jan Engelhardt <jengelh@inai.de>
Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
---
include/libipset/Makefile.am | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/libipset/Makefile.am b/include/libipset/Makefile.am
index 3b47518..79a1357 100644
--- a/include/libipset/Makefile.am
+++ b/include/libipset/Makefile.am
@@ -1,5 +1,6 @@
pkgincludedir = ${includedir}/libipset
pkginclude_HEADERS = \
+ args.h \
data.h \
errcode.h \
linux_ip_set_bitmap.h \
--
2.11.0

View File

@ -0,0 +1,84 @@
From c371154c65f7b09aa0582b7ae2f68aaf13113ee1 Mon Sep 17 00:00:00 2001
From: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Fri, 25 Jun 2021 22:30:40 +0200
Subject: [PATCH] lib: split parser from command execution
ipset_parse_argv() parses, builds and send the netlink messages to the
kernel. This patch extracts the parser and wrap it around the new
ipset_parser() function.
This patch comes is preparation for the ipset to nftables translation
infrastructure.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Jozsef Kadlecsik <kadlec@netfilter.org>
(cherry picked from commit 4dd0a5e5755ec058b78e3bd6da39fe2bb7bbb4f3)
---
lib/ipset.c | 44 ++++++++++++++++++++++++++++++--------------
1 file changed, 30 insertions(+), 14 deletions(-)
diff --git a/lib/ipset.c b/lib/ipset.c
index 6729919657707..3077f9793f841 100644
--- a/lib/ipset.c
+++ b/lib/ipset.c
@@ -923,20 +923,8 @@ static const char *cmd_prefix[] = {
[IPSET_TEST] = "test SETNAME",
};
-/* Workhorses */
-
-/**
- * ipset_parse_argv - parse and argv array and execute the command
- * @ipset: ipset structure
- * @argc: length of the array
- * @argv: array of strings
- *
- * Parse an array of strings and execute the ipset command.
- *
- * Returns 0 on success or a negative error code.
- */
-int
-ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[])
+static int
+ipset_parser(struct ipset *ipset, int oargc, char *oargv[])
{
int ret = 0;
enum ipset_cmd cmd = IPSET_CMD_NONE;
@@ -1280,6 +1268,34 @@ ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[])
if (argc > 1)
return ipset->custom_error(ipset, p, IPSET_PARAMETER_PROBLEM,
"Unknown argument %s", argv[1]);
+
+ return cmd;
+}
+
+/* Workhorses */
+
+/**
+ * ipset_parse_argv - parse and argv array and execute the command
+ * @ipset: ipset structure
+ * @argc: length of the array
+ * @argv: array of strings
+ *
+ * Parse an array of strings and execute the ipset command.
+ *
+ * Returns 0 on success or a negative error code.
+ */
+int
+ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[])
+{
+ struct ipset_session *session = ipset->session;
+ void *p = ipset_session_printf_private(session);
+ enum ipset_cmd cmd;
+ int ret;
+
+ cmd = ipset_parser(ipset, oargc, oargv);
+ if (cmd < 0)
+ return cmd;
+
ret = ipset_cmd(session, cmd, ipset->restore_line);
D("ret %d", ret);
/* In the case of warning, the return code is success */
--
2.38.0

View File

@ -0,0 +1,44 @@
From 5f8dc543a936f7f962165977cfb8e9e108659eb5 Mon Sep 17 00:00:00 2001
From: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Fri, 25 Jun 2021 22:30:41 +0200
Subject: [PATCH] lib: Detach restore routine from parser
Do not call restore() from ipset_parser(). Instead, ipset_parser()
returns the IPSET_CMD_RESTORE command and the caller invokes restore().
This patch comes in preparation for the ipset to nftables translation
infrastructure.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Jozsef Kadlecsik <kadlec@netfilter.org>
(cherry picked from commit ff7f000ef2dbe81444a4e204dbab9a2177c35e21)
---
lib/ipset.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/lib/ipset.c b/lib/ipset.c
index 3077f9793f841..5232d8b76c46f 100644
--- a/lib/ipset.c
+++ b/lib/ipset.c
@@ -1231,7 +1231,7 @@ ipset_parser(struct ipset *ipset, int oargc, char *oargv[])
return ipset->custom_error(ipset,
p, IPSET_PARAMETER_PROBLEM,
"Unknown argument %s", argv[1]);
- return restore(ipset);
+ return IPSET_CMD_RESTORE;
case IPSET_CMD_ADD:
case IPSET_CMD_DEL:
case IPSET_CMD_TEST:
@@ -1296,6 +1296,9 @@ ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[])
if (cmd < 0)
return cmd;
+ if (cmd == IPSET_CMD_RESTORE)
+ return restore(ipset);
+
ret = ipset_cmd(session, cmd, ipset->restore_line);
D("ret %d", ret);
/* In the case of warning, the return code is success */
--
2.38.0

View File

@ -0,0 +1,825 @@
From 469387c1fce52280daf0ed71a1e8cf1953551e8d Mon Sep 17 00:00:00 2001
From: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Fri, 25 Jun 2021 22:30:42 +0200
Subject: [PATCH] add ipset to nftables translation infrastructure
This patch provides the ipset-translate utility which allows you to
translate your existing ipset file to nftables.
The ipset-translate utility is actually a symlink to ipset, which checks
for 'argv[0] == ipset-translate' to exercise the translation path.
You can translate your ipset file through:
ipset-translate restore < sets.ipt
This patch reuses the existing parser and API to represent the sets and
the elements.
There is a new ipset_xlate_set dummy object that allows to store a
created set to fetch the type without interactions with the kernel.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Jozsef Kadlecsik <kadlec@netfilter.org>
(cherry picked from commit 325af556cd3a6d1636c0cd355b494c87f58397e0)
---
configure.ac | 1 +
include/libipset/Makefile.am | 3 +-
include/libipset/xlate.h | 6 +
lib/ipset.c | 541 ++++++++++++++++++++++++++++++++++-
src/Makefile.am | 8 +-
src/ipset-translate.8 | 91 ++++++
src/ipset.c | 8 +-
7 files changed, 654 insertions(+), 4 deletions(-)
create mode 100644 include/libipset/xlate.h
create mode 100644 src/ipset-translate.8
diff --git a/configure.ac b/configure.ac
index bd6116ca7f0a3..3ba3e17137d34 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,6 +7,7 @@ AC_CONFIG_HEADER([config.h])
AM_INIT_AUTOMAKE([foreign subdir-objects tar-pax])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+AC_PROG_LN_S
AC_ENABLE_STATIC
LT_INIT([dlopen])
LT_CONFIG_LTDL_DIR([libltdl])
diff --git a/include/libipset/Makefile.am b/include/libipset/Makefile.am
index c7f7b2bfce487..2c040291abc06 100644
--- a/include/libipset/Makefile.am
+++ b/include/libipset/Makefile.am
@@ -17,6 +17,7 @@ pkginclude_HEADERS = \
transport.h \
types.h \
ipset.h \
- utils.h
+ utils.h \
+ xlate.h
EXTRA_DIST = debug.h icmp.h icmpv6.h
diff --git a/include/libipset/xlate.h b/include/libipset/xlate.h
new file mode 100644
index 0000000000000..65697682f722d
--- /dev/null
+++ b/include/libipset/xlate.h
@@ -0,0 +1,6 @@
+#ifndef LIBIPSET_XLATE_H
+#define LIBIPSET_XLATE_H
+
+int ipset_xlate_argv(struct ipset *ipset, int argc, char *argv[]);
+
+#endif
diff --git a/lib/ipset.c b/lib/ipset.c
index 5232d8b76c46f..73e67db88e0d1 100644
--- a/lib/ipset.c
+++ b/lib/ipset.c
@@ -13,6 +13,7 @@
#include <stdio.h> /* printf */
#include <stdlib.h> /* exit */
#include <string.h> /* str* */
+#include <inttypes.h> /* PRIu64 */
#include <config.h>
@@ -28,6 +29,7 @@
#include <libipset/utils.h> /* STREQ */
#include <libipset/ipset.h> /* prototypes */
#include <libipset/ip_set_compiler.h> /* compiler attributes */
+#include <libipset/list_sort.h> /* lists */
static char program_name[] = PACKAGE;
static char program_version[] = PACKAGE_VERSION;
@@ -50,6 +52,17 @@ struct ipset {
char *newargv[MAX_ARGS];
int newargc;
const char *filename; /* Input/output filename */
+ bool xlate;
+ struct list_head xlate_sets;
+};
+
+struct ipset_xlate_set {
+ struct list_head list;
+ char name[IPSET_MAXNAMELEN];
+ uint8_t netmask;
+ uint8_t family;
+ bool interval;
+ const struct ipset_type *type;
};
/* Commands and environment options */
@@ -923,6 +936,31 @@ static const char *cmd_prefix[] = {
[IPSET_TEST] = "test SETNAME",
};
+static const struct ipset_xlate_set *
+ipset_xlate_set_get(struct ipset *ipset, const char *name)
+{
+ const struct ipset_xlate_set *set;
+
+ list_for_each_entry(set, &ipset->xlate_sets, list) {
+ if (!strcmp(set->name, name))
+ return set;
+ }
+
+ return NULL;
+}
+
+static const struct ipset_type *ipset_xlate_type_get(struct ipset *ipset,
+ const char *name)
+{
+ const struct ipset_xlate_set *set;
+
+ set = ipset_xlate_set_get(ipset, name);
+ if (!set)
+ return NULL;
+
+ return set->type;
+}
+
static int
ipset_parser(struct ipset *ipset, int oargc, char *oargv[])
{
@@ -1241,7 +1279,12 @@ ipset_parser(struct ipset *ipset, int oargc, char *oargv[])
if (ret < 0)
return ipset->standard_error(ipset, p);
- type = ipset_type_get(session, cmd);
+ if (!ipset->xlate) {
+ type = ipset_type_get(session, cmd);
+ } else {
+ type = ipset_xlate_type_get(ipset, arg0);
+ ipset_session_data_set(session, IPSET_OPT_TYPE, type);
+ }
if (type == NULL)
return ipset->standard_error(ipset, p);
@@ -1474,6 +1517,9 @@ ipset_init(void)
return NULL;
}
ipset_custom_printf(ipset, NULL, NULL, NULL, NULL);
+
+ INIT_LIST_HEAD(&ipset->xlate_sets);
+
return ipset;
}
@@ -1488,6 +1534,8 @@ ipset_init(void)
int
ipset_fini(struct ipset *ipset)
{
+ struct ipset_xlate_set *xlate_set, *next;
+
assert(ipset);
if (ipset->session)
@@ -1496,6 +1544,497 @@ ipset_fini(struct ipset *ipset)
if (ipset->newargv[0])
free(ipset->newargv[0]);
+ list_for_each_entry_safe(xlate_set, next, &ipset->xlate_sets, list)
+ free(xlate_set);
+
free(ipset);
return 0;
}
+
+/* Ignore the set family, use inet. */
+static const char *ipset_xlate_family(uint8_t family)
+{
+ return "inet";
+}
+
+enum ipset_xlate_set_type {
+ IPSET_XLATE_TYPE_UNKNOWN = 0,
+ IPSET_XLATE_TYPE_HASH_MAC,
+ IPSET_XLATE_TYPE_HASH_IP,
+ IPSET_XLATE_TYPE_HASH_IP_MAC,
+ IPSET_XLATE_TYPE_HASH_NET_IFACE,
+ IPSET_XLATE_TYPE_HASH_NET_PORT,
+ IPSET_XLATE_TYPE_HASH_NET_PORT_NET,
+ IPSET_XLATE_TYPE_HASH_NET_NET,
+ IPSET_XLATE_TYPE_HASH_NET,
+ IPSET_XLATE_TYPE_HASH_IP_PORT_NET,
+ IPSET_XLATE_TYPE_HASH_IP_PORT_IP,
+ IPSET_XLATE_TYPE_HASH_IP_MARK,
+ IPSET_XLATE_TYPE_HASH_IP_PORT,
+ IPSET_XLATE_TYPE_BITMAP_PORT,
+ IPSET_XLATE_TYPE_BITMAP_IP_MAC,
+ IPSET_XLATE_TYPE_BITMAP_IP,
+};
+
+static enum ipset_xlate_set_type ipset_xlate_set_type(const char *typename)
+{
+ if (!strcmp(typename, "hash:mac"))
+ return IPSET_XLATE_TYPE_HASH_MAC;
+ else if (!strcmp(typename, "hash:ip"))
+ return IPSET_XLATE_TYPE_HASH_IP;
+ else if (!strcmp(typename, "hash:ip,mac"))
+ return IPSET_XLATE_TYPE_HASH_IP_MAC;
+ else if (!strcmp(typename, "hash:net,iface"))
+ return IPSET_XLATE_TYPE_HASH_NET_IFACE;
+ else if (!strcmp(typename, "hash:net,port"))
+ return IPSET_XLATE_TYPE_HASH_NET_PORT;
+ else if (!strcmp(typename, "hash:net,port,net"))
+ return IPSET_XLATE_TYPE_HASH_NET_PORT_NET;
+ else if (!strcmp(typename, "hash:net,net"))
+ return IPSET_XLATE_TYPE_HASH_NET_NET;
+ else if (!strcmp(typename, "hash:net"))
+ return IPSET_XLATE_TYPE_HASH_NET;
+ else if (!strcmp(typename, "hash:ip,port,net"))
+ return IPSET_XLATE_TYPE_HASH_IP_PORT_NET;
+ else if (!strcmp(typename, "hash:ip,port,ip"))
+ return IPSET_XLATE_TYPE_HASH_IP_PORT_IP;
+ else if (!strcmp(typename, "hash:ip,mark"))
+ return IPSET_XLATE_TYPE_HASH_IP_MARK;
+ else if (!strcmp(typename, "hash:ip,port"))
+ return IPSET_XLATE_TYPE_HASH_IP_PORT;
+ else if (!strcmp(typename, "hash:ip"))
+ return IPSET_XLATE_TYPE_HASH_IP;
+ else if (!strcmp(typename, "bitmap:port"))
+ return IPSET_XLATE_TYPE_BITMAP_PORT;
+ else if (!strcmp(typename, "bitmap:ip,mac"))
+ return IPSET_XLATE_TYPE_BITMAP_IP_MAC;
+ else if (!strcmp(typename, "bitmap:ip"))
+ return IPSET_XLATE_TYPE_BITMAP_IP;
+
+ return IPSET_XLATE_TYPE_UNKNOWN;
+}
+
+#define NFT_SET_INTERVAL (1 << 0)
+
+static const char *
+ipset_xlate_type_to_nftables(int family, enum ipset_xlate_set_type type,
+ uint32_t *flags)
+{
+ switch (type) {
+ case IPSET_XLATE_TYPE_HASH_MAC:
+ return "ether_addr";
+ case IPSET_XLATE_TYPE_HASH_IP:
+ if (family == AF_INET)
+ return "ipv4_addr";
+ else if (family == AF_INET6)
+ return "ipv6_addr";
+ break;
+ case IPSET_XLATE_TYPE_HASH_IP_MAC:
+ if (family == AF_INET)
+ return "ipv4_addr . ether_addr";
+ else if (family == AF_INET6)
+ return "ipv6_addr . ether_addr";
+ break;
+ case IPSET_XLATE_TYPE_HASH_NET_IFACE:
+ *flags |= NFT_SET_INTERVAL;
+ if (family == AF_INET)
+ return "ipv4_addr . ifname";
+ else if (family == AF_INET6)
+ return "ipv6_addr . ifname";
+ break;
+ case IPSET_XLATE_TYPE_HASH_NET_PORT:
+ *flags |= NFT_SET_INTERVAL;
+ if (family == AF_INET)
+ return "ipv4_addr . inet_proto . inet_service";
+ else if (family == AF_INET6)
+ return "ipv6_addr . inet_proto . inet_service";
+ break;
+ case IPSET_XLATE_TYPE_HASH_NET_PORT_NET:
+ *flags |= NFT_SET_INTERVAL;
+ if (family == AF_INET)
+ return "ipv4_addr . inet_proto . inet_service . ipv4_addr";
+ else if (family == AF_INET6)
+ return "ipv6_addr . inet_proto . inet_service . ipv6_addr";
+ break;
+ case IPSET_XLATE_TYPE_HASH_NET_NET:
+ *flags |= NFT_SET_INTERVAL;
+ if (family == AF_INET)
+ return "ipv4_addr . ipv4_addr";
+ else if (family == AF_INET6)
+ return "ipv6_addr . ipv6_addr";
+ break;
+ case IPSET_XLATE_TYPE_HASH_NET:
+ *flags |= NFT_SET_INTERVAL;
+ if (family == AF_INET)
+ return "ipv4_addr";
+ else if (family == AF_INET6)
+ return "ipv6_addr";
+ break;
+ case IPSET_XLATE_TYPE_HASH_IP_PORT_NET:
+ *flags |= NFT_SET_INTERVAL;
+ if (family == AF_INET)
+ return "ipv4_addr . inet_proto . inet_service . ipv4_addr";
+ else if (family == AF_INET6)
+ return "ipv6_addr . inet_proto . inet_service . ipv6_addr";
+ break;
+ case IPSET_XLATE_TYPE_HASH_IP_PORT_IP:
+ if (family == AF_INET)
+ return "ipv4_addr . inet_proto . inet_service . ipv4_addr";
+ else if (family == AF_INET6)
+ return "ipv6_addr . inet_proto . inet_service . ipv6_addr";
+ break;
+ case IPSET_XLATE_TYPE_HASH_IP_MARK:
+ if (family == AF_INET)
+ return "ipv4_addr . mark";
+ else if (family == AF_INET6)
+ return "ipv6_addr . mark";
+ break;
+ case IPSET_XLATE_TYPE_HASH_IP_PORT:
+ if (family == AF_INET)
+ return "ipv4_addr . inet_proto . inet_service";
+ else if (family == AF_INET6)
+ return "ipv6_addr . inet_proto . inet_service";
+ break;
+ case IPSET_XLATE_TYPE_BITMAP_PORT:
+ return "inet_service";
+ case IPSET_XLATE_TYPE_BITMAP_IP_MAC:
+ if (family == AF_INET)
+ return "ipv4_addr . ether_addr";
+ else if (family == AF_INET6)
+ return "ipv6_addr . ether_addr";
+ break;
+ case IPSET_XLATE_TYPE_BITMAP_IP:
+ if (family == AF_INET)
+ return "ipv4_addr";
+ else if (family == AF_INET6)
+ return "ipv6_addr";
+ break;
+ }
+ /* This should not ever happen. */
+ return "unknown";
+}
+
+static int ipset_xlate(struct ipset *ipset, enum ipset_cmd cmd,
+ const char *table)
+{
+ const char *set, *typename, *nft_type;
+ const struct ipset_type *ipset_type;
+ struct ipset_xlate_set *xlate_set;
+ enum ipset_xlate_set_type type;
+ struct ipset_session *session;
+ const uint32_t *cadt_flags;
+ const uint32_t *timeout;
+ const uint32_t *maxelem;
+ struct ipset_data *data;
+ const uint8_t *netmask;
+ const char *comment;
+ uint32_t flags = 0;
+ uint8_t family;
+ char buf[64];
+ bool concat;
+ char *term;
+ int i;
+
+ session = ipset_session(ipset);
+ data = ipset_session_data(session);
+
+ set = ipset_data_get(data, IPSET_SETNAME);
+ family = ipset_data_family(data);
+
+ switch (cmd) {
+ case IPSET_CMD_CREATE:
+ /* Not supported. */
+ if (ipset_data_test(data, IPSET_OPT_MARKMASK)) {
+ printf("# %s", ipset->cmdline);
+ break;
+ }
+ cadt_flags = ipset_data_get(data, IPSET_OPT_CADT_FLAGS);
+
+ /* Ignore:
+ * - IPSET_FLAG_WITH_COMMENT
+ * - IPSET_FLAG_WITH_FORCEADD
+ */
+ if (cadt_flags &&
+ (*cadt_flags & (IPSET_FLAG_BEFORE |
+ IPSET_FLAG_PHYSDEV |
+ IPSET_FLAG_NOMATCH |
+ IPSET_FLAG_WITH_SKBINFO |
+ IPSET_FLAG_IFACE_WILDCARD))) {
+ printf("# %s", ipset->cmdline);
+ break;
+ }
+
+ typename = ipset_data_get(data, IPSET_OPT_TYPENAME);
+ type = ipset_xlate_set_type(typename);
+ nft_type = ipset_xlate_type_to_nftables(family, type, &flags);
+
+ printf("add set %s %s %s { type %s; ",
+ ipset_xlate_family(family), table, set, nft_type);
+ if (cadt_flags) {
+ if (*cadt_flags & IPSET_FLAG_WITH_COUNTERS)
+ printf("counter; ");
+ }
+ timeout = ipset_data_get(data, IPSET_OPT_TIMEOUT);
+ if (timeout)
+ printf("timeout %us; ", *timeout);
+ maxelem = ipset_data_get(data, IPSET_OPT_MAXELEM);
+ if (maxelem)
+ printf("size %u; ", *maxelem);
+
+ netmask = ipset_data_get(data, IPSET_OPT_NETMASK);
+ if (netmask &&
+ ((family == AF_INET && *netmask < 32) ||
+ (family == AF_INET6 && *netmask < 128)))
+ flags |= NFT_SET_INTERVAL;
+
+ if (flags & NFT_SET_INTERVAL)
+ printf("flags interval; ");
+
+ /* These create-specific options are safe to be ignored:
+ * - IPSET_OPT_GC
+ * - IPSET_OPT_HASHSIZE
+ * - IPSET_OPT_PROBES
+ * - IPSET_OPT_RESIZE
+ * - IPSET_OPT_SIZE
+ * - IPSET_OPT_FORCEADD
+ *
+ * Ranges and CIDR are safe to be ignored too:
+ * - IPSET_OPT_IP_FROM
+ * - IPSET_OPT_IP_TO
+ * - IPSET_OPT_PORT_FROM
+ * - IPSET_OPT_PORT_TO
+ */
+
+ printf("}\n");
+
+ xlate_set = calloc(1, sizeof(*xlate_set));
+ if (!xlate_set)
+ return -1;
+
+ snprintf(xlate_set->name, sizeof(xlate_set->name), "%s", set);
+ ipset_type = ipset_types();
+ while (ipset_type) {
+ if (!strcmp(ipset_type->name, typename))
+ break;
+ ipset_type = ipset_type->next;
+ }
+
+ xlate_set->family = family;
+ xlate_set->type = ipset_type;
+ if (netmask) {
+ xlate_set->netmask = *netmask;
+ xlate_set->interval = true;
+ }
+ list_add_tail(&xlate_set->list, &ipset->xlate_sets);
+ break;
+ case IPSET_CMD_DESTROY:
+ printf("del set %s %s %s\n",
+ ipset_xlate_family(family), table, set);
+ break;
+ case IPSET_CMD_FLUSH:
+ if (!set) {
+ printf("# %s", ipset->cmdline);
+ } else {
+ printf("flush set %s %s %s\n",
+ ipset_xlate_family(family), table, set);
+ }
+ break;
+ case IPSET_CMD_RENAME:
+ printf("# %s", ipset->cmdline);
+ return -1;
+ case IPSET_CMD_SWAP:
+ printf("# %s", ipset->cmdline);
+ return -1;
+ case IPSET_CMD_LIST:
+ if (!set) {
+ printf("list sets %s\n",
+ ipset_xlate_family(family), table);
+ } else {
+ printf("list set %s %s %s\n",
+ ipset_xlate_family(family), table, set);
+ }
+ break;
+ case IPSET_CMD_SAVE:
+ printf("# %s", ipset->cmdline);
+ return -1;
+ case IPSET_CMD_ADD:
+ case IPSET_CMD_DEL:
+ case IPSET_CMD_TEST:
+ /* Not supported. */
+ if (ipset_data_test(data, IPSET_OPT_NOMATCH) ||
+ ipset_data_test(data, IPSET_OPT_SKBINFO) ||
+ ipset_data_test(data, IPSET_OPT_SKBMARK) ||
+ ipset_data_test(data, IPSET_OPT_SKBPRIO) ||
+ ipset_data_test(data, IPSET_OPT_SKBQUEUE) ||
+ ipset_data_test(data, IPSET_OPT_IFACE_WILDCARD)) {
+ printf("# %s", ipset->cmdline);
+ break;
+ }
+ printf("%s element %s %s %s { ",
+ cmd == IPSET_CMD_ADD ? "add" :
+ cmd == IPSET_CMD_DEL ? "delete" : "get",
+ ipset_xlate_family(family), table, set);
+
+ typename = ipset_data_get(data, IPSET_OPT_TYPENAME);
+ type = ipset_xlate_set_type(typename);
+
+ xlate_set = (struct ipset_xlate_set *)
+ ipset_xlate_set_get(ipset, set);
+ if (xlate_set && xlate_set->interval)
+ netmask = &xlate_set->netmask;
+ else
+ netmask = NULL;
+
+ concat = false;
+ if (ipset_data_test(data, IPSET_OPT_IP)) {
+ ipset_print_data(buf, sizeof(buf), data, IPSET_OPT_IP, 0);
+ printf("%s", buf);
+ if (netmask)
+ printf("/%u ", *netmask);
+ else
+ printf(" ");
+
+ concat = true;
+ }
+ if (ipset_data_test(data, IPSET_OPT_MARK)) {
+ ipset_print_mark(buf, sizeof(buf), data, IPSET_OPT_MARK, 0);
+ printf("%s%s ", concat ? ". " : "", buf);
+ }
+ if (ipset_data_test(data, IPSET_OPT_IFACE)) {
+ ipset_print_data(buf, sizeof(buf), data, IPSET_OPT_IFACE, 0);
+ printf("%s%s ", concat ? ". " : "", buf);
+ }
+ if (ipset_data_test(data, IPSET_OPT_ETHER)) {
+ ipset_print_ether(buf, sizeof(buf), data, IPSET_OPT_ETHER, 0);
+ for (i = 0; i < strlen(buf); i++)
+ buf[i] = tolower(buf[i]);
+
+ printf("%s%s ", concat ? ". " : "", buf);
+ concat = true;
+ }
+ if (ipset_data_test(data, IPSET_OPT_PORT)) {
+ ipset_print_proto_port(buf, sizeof(buf), data, IPSET_OPT_PORT, 0);
+ term = strchr(buf, ':');
+ if (term) {
+ *term = '\0';
+ printf("%s%s ", concat ? ". " : "", buf);
+ }
+ ipset_print_data(buf, sizeof(buf), data, IPSET_OPT_PORT, 0);
+ printf("%s%s ", concat ? ". " : "", buf);
+ }
+ if (ipset_data_test(data, IPSET_OPT_IP2)) {
+ ipset_print_ip(buf, sizeof(buf), data, IPSET_OPT_IP2, 0);
+ printf("%s%s", concat ? ". " : "", buf);
+ if (netmask)
+ printf("/%u ", *netmask);
+ else
+ printf(" ");
+ }
+ if (ipset_data_test(data, IPSET_OPT_PACKETS) &&
+ ipset_data_test(data, IPSET_OPT_BYTES)) {
+ const uint64_t *pkts, *bytes;
+
+ pkts = ipset_data_get(data, IPSET_OPT_PACKETS);
+ bytes = ipset_data_get(data, IPSET_OPT_BYTES);
+
+ printf("counter packets %" PRIu64 " bytes %" PRIu64 " ",
+ *pkts, *bytes);
+ }
+ timeout = ipset_data_get(data, IPSET_OPT_TIMEOUT);
+ if (timeout)
+ printf("timeout %us ", *timeout);
+
+ comment = ipset_data_get(data, IPSET_OPT_ADT_COMMENT);
+ if (comment)
+ printf("comment \"%s\" ", comment);
+
+ printf("}\n");
+ break;
+ case IPSET_CMD_GET_BYNAME:
+ printf("# %s", ipset->cmdline);
+ return -1;
+ case IPSET_CMD_GET_BYINDEX:
+ printf("# %s", ipset->cmdline);
+ return -1;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int ipset_xlate_restore(struct ipset *ipset)
+{
+ struct ipset_session *session = ipset_session(ipset);
+ struct ipset_data *data = ipset_session_data(session);
+ void *p = ipset_session_printf_private(session);
+ const char *filename;
+ enum ipset_cmd cmd;
+ FILE *f = stdin;
+ int ret = 0;
+ char *c;
+
+ if (ipset->filename) {
+ f = fopen(ipset->filename, "r");
+ if (!f) {
+ fprintf(stderr, "cannot open file `%s'\n", filename);
+ return -1;
+ }
+ }
+
+ /* TODO: Allow to specify the table name other than 'global'. */
+ printf("add table inet global\n");
+
+ while (fgets(ipset->cmdline, sizeof(ipset->cmdline), f)) {
+ ipset->restore_line++;
+ c = ipset->cmdline;
+ while (isspace(c[0]))
+ c++;
+ if (c[0] == '\0' || c[0] == '#')
+ continue;
+ else if (STREQ(c, "COMMIT\n") || STREQ(c, "COMMIT\r\n"))
+ continue;
+
+ ret = build_argv(ipset, c);
+ if (ret < 0)
+ return ret;
+
+ cmd = ipset_parser(ipset, ipset->newargc, ipset->newargv);
+ if (cmd < 0)
+ ipset->standard_error(ipset, p);
+
+ /* TODO: Allow to specify the table name other than 'global'. */
+ ret = ipset_xlate(ipset, cmd, "global");
+ if (ret < 0)
+ break;
+
+ ipset_data_reset(data);
+ }
+
+ if (filename)
+ fclose(f);
+
+ return ret;
+}
+
+int ipset_xlate_argv(struct ipset *ipset, int argc, char *argv[])
+{
+ enum ipset_cmd cmd;
+ int ret;
+
+ ipset->xlate = true;
+
+ cmd = ipset_parser(ipset, argc, argv);
+ if (cmd < 0)
+ return cmd;
+
+ if (cmd == IPSET_CMD_RESTORE) {
+ ret = ipset_xlate_restore(ipset);
+ } else {
+ fprintf(stderr, "This command is not supported, "
+ "use `ipset-translate restore < file'\n");
+ ret = -1;
+ }
+
+ return ret;
+}
diff --git a/src/Makefile.am b/src/Makefile.am
index 438fcec0f1f10..95dea07701391 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -12,10 +12,16 @@ AM_LDFLAGS = -static
endif
endif
-dist_man_MANS = ipset.8
+dist_man_MANS = ipset.8 ipset-translate.8
sparse-check: $(ipset_SOURCES:.c=.d)
%.d: %.c
$(IPSET_AM_V_CHECK)\
$(SPARSE) -I.. $(SPARSE_FLAGS) $(AM_CFLAGS) $(AM_CPPFLAGS) $< || :
+
+install-exec-hook:
+ ${LN_S} -f "${sbindir}/ipset" "${DESTDIR}${sbindir}/ipset-translate";
+
+uninstall-hook:
+ rm -f ${DESTDIR}${sbindir}/ipset-translate
diff --git a/src/ipset-translate.8 b/src/ipset-translate.8
new file mode 100644
index 0000000000000..bb4e737e14806
--- /dev/null
+++ b/src/ipset-translate.8
@@ -0,0 +1,91 @@
+.\"
+.\" (C) Copyright 2021, Pablo Neira Ayuso <pablo@netfilter.org>
+.\"
+.\" %%%LICENSE_START(GPLv2+_DOC_FULL)
+.\" This is free documentation; 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.
+.\"
+.\" The GNU General Public License's references to "object code"
+.\" and "executables" are to be interpreted as the output of any
+.\" document formatting or typesetting system, including
+.\" intermediate and printed output.
+.\"
+.\" This manual 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 manual; if not, see
+.\" <http://www.gnu.org/licenses/>.
+.\" %%%LICENSE_END
+.\"
+.TH IPSET-TRANSLATE 8 "May 31, 2021"
+
+.SH NAME
+ipset-translate \(em translation tool to migrate from ipset to nftables
+.SH DESCRIPTION
+This tool allows system administrators to translate a given IP sets file
+to \fBnftables(8)\fP.
+
+The only available command is:
+
+.IP \[bu] 2
+ipset-translate restores < file.ipt
+
+.SH USAGE
+The \fBipset-translate\fP tool reads an IP sets file in the syntax produced by
+\fBipset(8)\fP save. No set modifications occur, this tool is a text converter.
+
+.SH EXAMPLES
+Basic operation examples.
+
+Single command translation, assuming the original file:
+
+.nf
+create test1 hash:ip,port family inet counters timeout 300 hashsize 1024 maxelem 65536 bucketsize 12 initval 0xb5c4be5d
+add test1 1.1.1.1,udp:20
+add test1 1.1.1.1,21
+create test2 hash:ip,port family inet hashsize 1024 maxelem 65536 bucketsize 12 initval 0xb5c4be5d
+.fi
+
+which results in the following translation:
+
+.nf
+root@machine:~# ipset-translate restore < file.ipt
+add set inet global test1 { type ipv4_addr . inet_proto . inet_service; counter; timeout 300s; size 65536; }
+add element inet global test1 { 1.1.1.1 . udp . 20 }
+add element inet global test1 { 1.1.1.1 . tcp . 21 }
+add set inet global test2 { type ipv4_addr . inet_proto . inet_service; size 65536; }
+.fi
+
+.SH LIMITATIONS
+A few IP sets options may be not supported because they are not yet implemented
+in \fBnftables(8)\fP.
+
+Contrary to \fBnftables(8)\fP, IP sets are not attached to a specific table.
+The translation utility assumes that sets are created in a table whose name
+is \fBglobal\fP and family is \fBinet\fP. You might want to update the
+resulting translation to use a different table name and family for your sets.
+
+To get up-to-date information about this, please head to
+\fBhttps://wiki.nftables.org/\fP.
+
+.SH SEE ALSO
+\fBnft(8)\fP, \fBipset(8)\fP
+
+.SH AUTHORS
+The nftables framework has been written by the Netfilter Project
+(https://www.netfilter.org).
+
+This manual page was written by Pablo Neira Ayuso
+<pablo@netfilter.org>.
+
+This documentation is free/libre under the terms of the GPLv2+.
+
+This tool was funded through the NGI0 PET Fund, a fund established by NLnet with
+financial support from the European Commission's Next Generation Internet
+programme, under the aegis of DG Communications Networks, Content and Technology
+under grant agreement No 825310.
diff --git a/src/ipset.c b/src/ipset.c
index ee36a06e595de..6d42b60d2fe9d 100644
--- a/src/ipset.c
+++ b/src/ipset.c
@@ -9,9 +9,11 @@
#include <assert.h> /* assert */
#include <stdio.h> /* fprintf */
#include <stdlib.h> /* exit */
+#include <string.h> /* strcmp */
#include <config.h>
#include <libipset/ipset.h> /* ipset library */
+#include <libipset/xlate.h> /* translate to nftables */
int
main(int argc, char *argv[])
@@ -29,7 +31,11 @@ main(int argc, char *argv[])
exit(1);
}
- ret = ipset_parse_argv(ipset, argc, argv);
+ if (!strcmp(argv[0], "ipset-translate")) {
+ ret = ipset_xlate_argv(ipset, argc, argv);
+ } else {
+ ret = ipset_parse_argv(ipset, argc, argv);
+ }
ipset_fini(ipset);
--
2.38.0

View File

@ -0,0 +1,186 @@
From 55554de816520471e11f39b99468d5777ae57937 Mon Sep 17 00:00:00 2001
From: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Fri, 25 Jun 2021 22:30:43 +0200
Subject: [PATCH] tests: add tests ipset to nftables
This test checks that the translation from ipset to nftables is correct.
term$ cd tests/xlate
term$ ./runtest.sh
in case that the translation is not correct, it shows the diff with expected
translation output.
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Jozsef Kadlecsik <kadlec@netfilter.org>
(cherry picked from commit 7587d1c4b5465f3b5315536b439b63a5ffe0311d)
---
tests/xlate/runtest.sh | 29 +++++++++++++++++++++
tests/xlate/xlate.t | 55 ++++++++++++++++++++++++++++++++++++++++
tests/xlate/xlate.t.nft | 56 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 140 insertions(+)
create mode 100755 tests/xlate/runtest.sh
create mode 100644 tests/xlate/xlate.t
create mode 100644 tests/xlate/xlate.t.nft
diff --git a/tests/xlate/runtest.sh b/tests/xlate/runtest.sh
new file mode 100755
index 0000000000000..a2a02c05d7573
--- /dev/null
+++ b/tests/xlate/runtest.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+DIFF=$(which diff)
+if [ ! -x "$DIFF" ] ; then
+ echo "ERROR: missing diff"
+ exit 1
+fi
+
+IPSET_XLATE=$(which ipset-translate)
+if [ ! -x "$IPSET_XLATE" ] ; then
+ echo "ERROR: ipset-translate is not installed yet"
+ exit 1
+fi
+
+TMP=$(mktemp)
+ipset-translate restore < xlate.t &> $TMP
+if [ $? -ne 0 ]
+then
+ cat $TMP
+ echo -e "[\033[0;31mERROR\033[0m] failed to run ipset-translate"
+ exit 1
+fi
+${DIFF} -u xlate.t.nft $TMP
+if [ $? -eq 0 ]
+then
+ echo -e "[\033[0;32mOK\033[0m] tests are fine!"
+else
+ echo -e "[\033[0;31mERROR\033[0m] unexpected ipset to nftables translation"
+fi
diff --git a/tests/xlate/xlate.t b/tests/xlate/xlate.t
new file mode 100644
index 0000000000000..b1e7d288e2a98
--- /dev/null
+++ b/tests/xlate/xlate.t
@@ -0,0 +1,55 @@
+create hip1 hash:ip
+add hip1 192.168.10.2
+add hip1 192.168.10.3
+create hip2 hash:ip hashsize 128 bucketsize 255 timeout 4
+add hip2 192.168.10.3
+add hip2 192.168.10.4 timeout 10
+create hip3 hash:ip counters
+add hip3 192.168.10.3 packets 5 bytes 3456
+create hip4 hash:ip netmask 24
+add hip4 192.168.10.0
+create hip5 hash:ip maxelem 24
+add hip5 192.168.10.0
+create hip6 hash:ip comment
+add hip5 192.168.10.1
+add hip5 192.168.10.2 comment "this is a comment"
+create ipp1 hash:ip,port
+add ipp1 192.168.10.1,0
+add ipp1 192.168.10.2,5
+create ipp2 hash:ip,port timeout 4
+add ipp2 192.168.10.1,0 timeout 12
+add ipp2 192.168.10.2,5
+create ipp3 hash:ip,port counters
+add ipp3 192.168.10.3,20 packets 5 bytes 3456
+create ipp4 hash:ip,port timeout 4 counters
+add ipp4 192.168.10.3,20 packets 5 bytes 3456
+create bip1 bitmap:ip range 2.0.0.1-2.1.0.1 timeout 5
+create bip2 bitmap:ip range 10.0.0.0/8 netmask 24 timeout 5
+add bip2 10.10.10.0
+add bip2 10.10.20.0 timeout 12
+create net1 hash:net
+add net1 192.168.10.0/24
+create net2 hash:net,net
+add net2 192.168.10.0/24,192.168.20.0/24
+create hm1 hash:mac
+add hm1 aa:bb:cc:dd:ee:ff
+create him1 hash:ip,mac
+add him1 1.1.1.1,aa:bb:cc:dd:ee:ff
+create ni1 hash:net,iface
+add ni1 1.1.1.0/24,eth0
+create nip1 hash:net,port
+add nip1 1.1.1.0/24,22
+create npn1 hash:net,port,net
+add npn1 1.1.1.0/24,22,2.2.2.0/24
+create nn1 hash:net,net
+add nn1 1.1.1.0/24,2.2.2.0/24
+create ipn1 hash:ip,port,net
+add ipn1 1.1.1.1,22,2.2.2.0/24
+create ipi1 hash:ip,port,ip
+add ipi1 1.1.1.1,22,2.2.2.2
+create im1 hash:ip,mark
+add im1 1.1.1.1,0x123456
+create bp1 bitmap:port range 1-1024
+add bp1 22
+create bim1 bitmap:ip,mac range 1.1.1.0/24
+add bim1 1.1.1.1,aa:bb:cc:dd:ee:ff
diff --git a/tests/xlate/xlate.t.nft b/tests/xlate/xlate.t.nft
new file mode 100644
index 0000000000000..96eba3b0175ea
--- /dev/null
+++ b/tests/xlate/xlate.t.nft
@@ -0,0 +1,56 @@
+add table inet global
+add set inet global hip1 { type ipv4_addr; }
+add element inet global hip1 { 192.168.10.2 }
+add element inet global hip1 { 192.168.10.3 }
+add set inet global hip2 { type ipv4_addr; timeout 4s; }
+add element inet global hip2 { 192.168.10.3 }
+add element inet global hip2 { 192.168.10.4 timeout 10s }
+add set inet global hip3 { type ipv4_addr; counter; }
+add element inet global hip3 { 192.168.10.3 counter packets 5 bytes 3456 }
+add set inet global hip4 { type ipv4_addr; flags interval; }
+add element inet global hip4 { 192.168.10.0/24 }
+add set inet global hip5 { type ipv4_addr; size 24; }
+add element inet global hip5 { 192.168.10.0 }
+add set inet global hip6 { type ipv4_addr; }
+add element inet global hip5 { 192.168.10.1 }
+add element inet global hip5 { 192.168.10.2 comment "this is a comment" }
+add set inet global ipp1 { type ipv4_addr . inet_proto . inet_service; }
+add element inet global ipp1 { 192.168.10.1 . tcp . 0 }
+add element inet global ipp1 { 192.168.10.2 . tcp . 5 }
+add set inet global ipp2 { type ipv4_addr . inet_proto . inet_service; timeout 4s; }
+add element inet global ipp2 { 192.168.10.1 . tcp . 0 timeout 12s }
+add element inet global ipp2 { 192.168.10.2 . tcp . 5 }
+add set inet global ipp3 { type ipv4_addr . inet_proto . inet_service; counter; }
+add element inet global ipp3 { 192.168.10.3 . tcp . 20 counter packets 5 bytes 3456 }
+add set inet global ipp4 { type ipv4_addr . inet_proto . inet_service; counter; timeout 4s; }
+add element inet global ipp4 { 192.168.10.3 . tcp . 20 counter packets 5 bytes 3456 }
+add set inet global bip1 { type ipv4_addr; timeout 5s; }
+add set inet global bip2 { type ipv4_addr; timeout 5s; flags interval; }
+add element inet global bip2 { 10.10.10.0/24 }
+add element inet global bip2 { 10.10.20.0/24 timeout 12s }
+add set inet global net1 { type ipv4_addr; flags interval; }
+add element inet global net1 { 192.168.10.0/24 }
+add set inet global net2 { type ipv4_addr . ipv4_addr; flags interval; }
+add element inet global net2 { 192.168.10.0/24 . 192.168.20.0/24 }
+add set inet global hm1 { type ether_addr; }
+add element inet global hm1 { aa:bb:cc:dd:ee:ff }
+add set inet global him1 { type ipv4_addr . ether_addr; }
+add element inet global him1 { 1.1.1.1 . aa:bb:cc:dd:ee:ff }
+add set inet global ni1 { type ipv4_addr . ifname; flags interval; }
+add element inet global ni1 { 1.1.1.0/24 . eth0 }
+add set inet global nip1 { type ipv4_addr . inet_proto . inet_service; flags interval; }
+add element inet global nip1 { 1.1.1.0/24 . tcp . 22 }
+add set inet global npn1 { type ipv4_addr . inet_proto . inet_service . ipv4_addr; flags interval; }
+add element inet global npn1 { 1.1.1.0/24 . tcp . 22 . 2.2.2.0/24 }
+add set inet global nn1 { type ipv4_addr . ipv4_addr; flags interval; }
+add element inet global nn1 { 1.1.1.0/24 . 2.2.2.0/24 }
+add set inet global ipn1 { type ipv4_addr . inet_proto . inet_service . ipv4_addr; flags interval; }
+add element inet global ipn1 { 1.1.1.1 . tcp . 22 . 2.2.2.0/24 }
+add set inet global ipi1 { type ipv4_addr . inet_proto . inet_service . ipv4_addr; }
+add element inet global ipi1 { 1.1.1.1 . tcp . 22 . 2.2.2.2 }
+add set inet global im1 { type ipv4_addr . mark; }
+add element inet global im1 { 1.1.1.1 . 0x00123456 }
+add set inet global bp1 { type inet_service; }
+add element inet global bp1 { 22 }
+add set inet global bim1 { type ipv4_addr . ether_addr; }
+add element inet global bim1 { 1.1.1.1 . aa:bb:cc:dd:ee:ff }
--
2.38.0

View File

@ -0,0 +1,32 @@
From ad4513664b99f5913578ee9771836997f88f4c96 Mon Sep 17 00:00:00 2001
From: "Bernhard M. Wiedemann" <bwiedemann@suse.de>
Date: Wed, 29 Sep 2021 09:55:43 +0200
Subject: [PATCH] Fix typo in ipset-translate man page
originally reported in
https://lists.opensuse.org/archives/list/factory@lists.opensuse.org/thread/ZIXKNQHSSCQ4ZLEGYYKLAXQ4PQ5EYFGZ/
by Larry Len Rainey
Signed-off-by: Bernhard M. Wiedemann <bwiedemann@suse.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit c74a420471fd693f89e0b0e19f93c88af22fb7de)
---
src/ipset-translate.8 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/ipset-translate.8 b/src/ipset-translate.8
index bb4e737e14806..55ce2a99f2cf2 100644
--- a/src/ipset-translate.8
+++ b/src/ipset-translate.8
@@ -33,7 +33,7 @@ to \fBnftables(8)\fP.
The only available command is:
.IP \[bu] 2
-ipset-translate restores < file.ipt
+ipset-translate restore < file.ipt
.SH USAGE
The \fBipset-translate\fP tool reads an IP sets file in the syntax produced by
--
2.38.0

View File

@ -0,0 +1,92 @@
From 343650906603dff56f766d1fbcef1de64a98e14a Mon Sep 17 00:00:00 2001
From: Pablo Neira Ayuso <pablo@netfilter.org>
Date: Mon, 28 Feb 2022 19:52:57 +0100
Subject: [PATCH] Fix IPv6 sets nftables translation
The parser assumes the set is an IPv4 ipset because IPSET_OPT_FAMILY is
not set.
# ipset-translate restore < ./ipset-mwan3_set_connected_ipv6.dump
add table inet global
add set inet global mwan3_connected_v6 { type ipv6_addr; flags interval; }
flush set inet global mwan3_connected_v6
ipset v7.15: Error in line 4: Syntax error: '64' is out of range 0-32
Remove ipset_xlate_type_get(), call ipset_xlate_set_get() instead to
obtain the set type and family.
Reported-by: Florian Eckert <fe@dev.tdt.de>
Fixes: 325af556cd3a ("add ipset to nftables translation infrastructure")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit be7f6099feb7b5d34715b06f9308877cdcdc404a)
---
lib/ipset.c | 24 ++++++++++--------------
tests/xlate/xlate.t | 2 ++
tests/xlate/xlate.t.nft | 2 ++
3 files changed, 14 insertions(+), 14 deletions(-)
diff --git a/lib/ipset.c b/lib/ipset.c
index 73e67db88e0d1..50f86aee045bc 100644
--- a/lib/ipset.c
+++ b/lib/ipset.c
@@ -949,18 +949,6 @@ ipset_xlate_set_get(struct ipset *ipset, const char *name)
return NULL;
}
-static const struct ipset_type *ipset_xlate_type_get(struct ipset *ipset,
- const char *name)
-{
- const struct ipset_xlate_set *set;
-
- set = ipset_xlate_set_get(ipset, name);
- if (!set)
- return NULL;
-
- return set->type;
-}
-
static int
ipset_parser(struct ipset *ipset, int oargc, char *oargv[])
{
@@ -1282,8 +1270,16 @@ ipset_parser(struct ipset *ipset, int oargc, char *oargv[])
if (!ipset->xlate) {
type = ipset_type_get(session, cmd);
} else {
- type = ipset_xlate_type_get(ipset, arg0);
- ipset_session_data_set(session, IPSET_OPT_TYPE, type);
+ const struct ipset_xlate_set *xlate_set;
+
+ xlate_set = ipset_xlate_set_get(ipset, arg0);
+ if (xlate_set) {
+ ipset_session_data_set(session, IPSET_OPT_TYPE,
+ xlate_set->type);
+ ipset_session_data_set(session, IPSET_OPT_FAMILY,
+ &xlate_set->family);
+ type = xlate_set->type;
+ }
}
if (type == NULL)
return ipset->standard_error(ipset, p);
diff --git a/tests/xlate/xlate.t b/tests/xlate/xlate.t
index b1e7d288e2a98..f09cb202bb6c0 100644
--- a/tests/xlate/xlate.t
+++ b/tests/xlate/xlate.t
@@ -53,3 +53,5 @@ create bp1 bitmap:port range 1-1024
add bp1 22
create bim1 bitmap:ip,mac range 1.1.1.0/24
add bim1 1.1.1.1,aa:bb:cc:dd:ee:ff
+create hn6 hash:net family inet6
+add hn6 fe80::/64
diff --git a/tests/xlate/xlate.t.nft b/tests/xlate/xlate.t.nft
index 96eba3b0175ea..0152a30811258 100644
--- a/tests/xlate/xlate.t.nft
+++ b/tests/xlate/xlate.t.nft
@@ -54,3 +54,5 @@ add set inet global bp1 { type inet_service; }
add element inet global bp1 { 22 }
add set inet global bim1 { type ipv4_addr . ether_addr; }
add element inet global bim1 { 1.1.1.1 . aa:bb:cc:dd:ee:ff }
+add set inet global hn6 { type ipv6_addr; flags interval; }
+add element inet global hn6 { fe80::/64 }
--
2.38.0

View File

@ -0,0 +1,47 @@
From a7d1e05c0fcae89fffcd5aa235ea32d16becbd21 Mon Sep 17 00:00:00 2001
From: Quentin Armitage <quentin@armitage.org.uk>
Date: Thu, 11 Aug 2022 17:52:18 +0100
Subject: [PATCH] ipset-translate: allow invoking with a path name
Executing /usr/sbin/ipset-translate results in the ipset functionality being run, rather than the ipset-translate functionality.
# ipset-translate destroy fred
This command is not supported, use `ipset-translate restore < file'
# /usr/sbin/ipset-translate destroy fred
ipset v7.15: The set with the given name does not exist
use basename() to resolve the issue.
Closes: https://bugzilla.netfilter.org/show_bug.cgi?id=1626
Signed-off-by: Quentin Armitage <quentin@armitage.org.uk>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
(cherry picked from commit e1b60b2a93356c313cccb2abfdae4b58d530e02b)
---
src/ipset.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/ipset.c b/src/ipset.c
index 6d42b60d2fe9d..162f477d49cd0 100644
--- a/src/ipset.c
+++ b/src/ipset.c
@@ -6,6 +6,7 @@
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
+#define _GNU_SOURCE
#include <assert.h> /* assert */
#include <stdio.h> /* fprintf */
#include <stdlib.h> /* exit */
@@ -31,7 +32,7 @@ main(int argc, char *argv[])
exit(1);
}
- if (!strcmp(argv[0], "ipset-translate")) {
+ if (!strcmp(basename(argv[0]), "ipset-translate")) {
ret = ipset_xlate_argv(ipset, argc, argv);
} else {
ret = ipset_parse_argv(ipset, argc, argv);
--
2.38.0

View File

@ -0,0 +1,171 @@
From aba564ecc621345fcfea2fe883cbfd8d02e54026 Mon Sep 17 00:00:00 2001
From: Jozsef Kadlecsik <kadlec@netfilter.org>
Date: Sun, 20 Nov 2022 22:43:59 +0100
Subject: [PATCH] Fix all debug mode warnings
(cherry picked from commit e39e3466d2d38cdfe83447f391b550e607bc3ce8)
Conflicts:
lib/parse.c
- Fixed code does not exist due to missing commit 79184e760edfb
("Add missing hunk to patch "Allow specifying protocols by number"")
---
include/libipset/list_sort.h | 4 ++--
lib/ipset.c | 32 +++++++++++++++++++-------------
2 files changed, 21 insertions(+), 15 deletions(-)
diff --git a/include/libipset/list_sort.h b/include/libipset/list_sort.h
index 70bb02d3d1b68..d9d7b36b8380f 100644
--- a/include/libipset/list_sort.h
+++ b/include/libipset/list_sort.h
@@ -61,7 +61,7 @@ static inline void list_del(struct list_head *entry)
// entry->prev = (void *) 0;
}
-static inline void __list_splice(const struct list_head *list,
+static inline void __list_splice(struct list_head *list,
struct list_head *prev,
struct list_head *next)
{
@@ -75,7 +75,7 @@ static inline void __list_splice(const struct list_head *list,
next->prev = last;
}
-static inline void list_splice(const struct list_head *list,
+static inline void list_splice(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list))
diff --git a/lib/ipset.c b/lib/ipset.c
index 50f86aee045bc..f57b07413cba5 100644
--- a/lib/ipset.c
+++ b/lib/ipset.c
@@ -30,6 +30,7 @@
#include <libipset/ipset.h> /* prototypes */
#include <libipset/ip_set_compiler.h> /* compiler attributes */
#include <libipset/list_sort.h> /* lists */
+#include <libipset/xlate.h> /* ipset_xlate_argv */
static char program_name[] = PACKAGE;
static char program_version[] = PACKAGE_VERSION;
@@ -936,10 +937,10 @@ static const char *cmd_prefix[] = {
[IPSET_TEST] = "test SETNAME",
};
-static const struct ipset_xlate_set *
+static struct ipset_xlate_set *
ipset_xlate_set_get(struct ipset *ipset, const char *name)
{
- const struct ipset_xlate_set *set;
+ struct ipset_xlate_set *set;
list_for_each_entry(set, &ipset->xlate_sets, list) {
if (!strcmp(set->name, name))
@@ -958,7 +959,7 @@ ipset_parser(struct ipset *ipset, int oargc, char *oargv[])
char *arg0 = NULL, *arg1 = NULL;
const struct ipset_envopts *opt;
const struct ipset_commands *command;
- const struct ipset_type *type;
+ const struct ipset_type *type = NULL;
struct ipset_session *session = ipset->session;
void *p = ipset_session_printf_private(session);
int argc = oargc;
@@ -1127,6 +1128,7 @@ ipset_parser(struct ipset *ipset, int oargc, char *oargv[])
if (arg0) {
const struct ipset_arg *arg;
int k;
+ enum ipset_adt c;
/* Type-specific help, without kernel checking */
type = type_find(arg0);
@@ -1136,11 +1138,11 @@ ipset_parser(struct ipset *ipset, int oargc, char *oargv[])
"Unknown settype: `%s'", arg0);
printf("\n%s type specific options:\n\n", type->name);
for (i = 0; cmd_help_order[i] != IPSET_CADT_MAX; i++) {
- cmd = cmd_help_order[i];
+ c = cmd_help_order[i];
printf("%s %s %s\n",
- cmd_prefix[cmd], type->name, type->cmd[cmd].help);
- for (k = 0; type->cmd[cmd].args[k] != IPSET_ARG_NONE; k++) {
- arg = ipset_keyword(type->cmd[cmd].args[k]);
+ cmd_prefix[c], type->name, type->cmd[c].help);
+ for (k = 0; type->cmd[c].args[k] != IPSET_ARG_NONE; k++) {
+ arg = ipset_keyword(type->cmd[c].args[k]);
if (!arg->help || arg->help[0] == '\0')
continue;
printf(" %s\n", arg->help);
@@ -1548,7 +1550,7 @@ ipset_fini(struct ipset *ipset)
}
/* Ignore the set family, use inet. */
-static const char *ipset_xlate_family(uint8_t family)
+static const char *ipset_xlate_family(uint8_t family UNUSED)
{
return "inet";
}
@@ -1705,6 +1707,10 @@ ipset_xlate_type_to_nftables(int family, enum ipset_xlate_set_type type,
else if (family == AF_INET6)
return "ipv6_addr";
break;
+ case IPSET_XLATE_TYPE_UNKNOWN:
+ break;
+ default:
+ break;
}
/* This should not ever happen. */
return "unknown";
@@ -1729,7 +1735,6 @@ static int ipset_xlate(struct ipset *ipset, enum ipset_cmd cmd,
char buf[64];
bool concat;
char *term;
- int i;
session = ipset_session(ipset);
data = ipset_session_data(session);
@@ -1843,7 +1848,7 @@ static int ipset_xlate(struct ipset *ipset, enum ipset_cmd cmd,
return -1;
case IPSET_CMD_LIST:
if (!set) {
- printf("list sets %s\n",
+ printf("list sets %s %s\n",
ipset_xlate_family(family), table);
} else {
printf("list set %s %s %s\n",
@@ -1902,6 +1907,8 @@ static int ipset_xlate(struct ipset *ipset, enum ipset_cmd cmd,
}
if (ipset_data_test(data, IPSET_OPT_ETHER)) {
ipset_print_ether(buf, sizeof(buf), data, IPSET_OPT_ETHER, 0);
+ size_t i;
+
for (i = 0; i < strlen(buf); i++)
buf[i] = tolower(buf[i]);
@@ -1964,7 +1971,6 @@ static int ipset_xlate_restore(struct ipset *ipset)
struct ipset_session *session = ipset_session(ipset);
struct ipset_data *data = ipset_session_data(session);
void *p = ipset_session_printf_private(session);
- const char *filename;
enum ipset_cmd cmd;
FILE *f = stdin;
int ret = 0;
@@ -1973,7 +1979,7 @@ static int ipset_xlate_restore(struct ipset *ipset)
if (ipset->filename) {
f = fopen(ipset->filename, "r");
if (!f) {
- fprintf(stderr, "cannot open file `%s'\n", filename);
+ fprintf(stderr, "cannot open file `%s'\n", ipset->filename);
return -1;
}
}
@@ -2007,7 +2013,7 @@ static int ipset_xlate_restore(struct ipset *ipset)
ipset_data_reset(data);
}
- if (filename)
+ if (ipset->filename)
fclose(f);
return ret;
--
2.38.0

View File

@ -0,0 +1,44 @@
From 68a945a5c140b3067e90baae3f35441dd8bacf25 Mon Sep 17 00:00:00 2001
From: Jozsef Kadlecsik <kadlec@netfilter.org>
Date: Wed, 28 Jul 2021 16:02:49 +0200
Subject: [PATCH] Add missing function to libipset.map and bump library version
A new function was not added to libipset.map at the previous release,
fix it. Reported by Jan Engelhardt.
Signed-off-by: Jozsef Kadlecsik <kadlec@netfilter.org>
(cherry picked from commit 8a0df0c759cf9f0ca6f0cfa512ebf4832fd73729)
---
Make_global.am | 2 +-
lib/libipset.map | 5 +++++
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/Make_global.am b/Make_global.am
index 3ad7f73b28479..ed92cfec7a207 100644
--- a/Make_global.am
+++ b/Make_global.am
@@ -69,7 +69,7 @@
# interface.
# curr:rev:age
-LIBVERSION = 15:0:2
+LIBVERSION = 16:0:3
AM_CPPFLAGS = $(kinclude_CFLAGS) $(all_includes) -I$(top_srcdir)/include
diff --git a/lib/libipset.map b/lib/libipset.map
index 12d16a4faf53c..c380f9cde2edc 100644
--- a/lib/libipset.map
+++ b/lib/libipset.map
@@ -208,3 +208,8 @@ LIBIPSET_4.10 {
ipset_print_hexnumber;
} LIBIPSET_4.9;
+LIBIPSET_4.11 {
+global:
+ ipset_xlate_argv;
+} LIBIPSET_4.10;
+
--
2.38.0

7
gating.yaml Normal file
View File

@ -0,0 +1,7 @@
--- !Policy
product_versions:
- rhel-9
decision_context: osci_compose_gate
rules:
# - !PassingTestCaseRule {test_case_name: osci.brew-build.tier0.functional}
- !PassingTestCaseRule {test_case_name: baseos-ci.brew-build.tier1-gating.functional}

5
ipset-config Normal file
View File

@ -0,0 +1,5 @@
# Save current ipsets on stop.
# Value: yes|no, default: no
# Saves all ipsets to /etc/ipset/ipset if service gets stopped
# (e.g. on system shutdown).
IPSET_SAVE_ON_STOP="no"

2
ipset.save-legacy Normal file
View File

@ -0,0 +1,2 @@
#!/bin/bash
exec /usr/libexec/ipset/ipset.start-stop save

View File

@ -9,10 +9,11 @@ RemainAfterExit=yes
ExecStart=/usr/libexec/ipset/ipset.start-stop start
ExecStop=/usr/libexec/ipset/ipset.start-stop stop
ExecReload=/usr/libexec/ipset/ipset.start-stop reload
# Save current ipset entries on stop/restart.
# Save current ipset entries on stop.
# Value: yes|no, default: no
# Saves all ipsets to /etc/ipset/ipset if ipset gets stopped
Environment=IPSET_SAVE_ON_STOP=no IPSET_SAVE_ON_RESTART=no
# Saves all ipsets to /etc/sysconfig/ipset if ipset gets stopped
Environment=IPSET_SAVE_ON_STOP=no
EnvironmentFile=-/etc/sysconfig/ipset-config
[Install]
WantedBy=basic.target

View File

@ -1,6 +1,9 @@
# service legacy actions
%define legacy_actions %{_libexecdir}/initscripts/legacy-actions
Name: ipset
Version: 7.10
Release: 2%{?dist}
Version: 7.11
Release: 8%{?dist}
Summary: Manage Linux IP sets
License: GPLv2
@ -8,6 +11,19 @@ URL: http://ipset.netfilter.org/
Source0: %{url}/%{name}-%{version}.tar.bz2
Source1: %{name}.service
Source2: %{name}.start-stop
Source3: %{name}-config
Source4: %{name}.save-legacy
Patch1: 0001-Add-deprecation-notice-to-ipset.8.patch
Patch2: 0002-lib-split-parser-from-command-execution.patch
Patch3: 0003-lib-Detach-restore-routine-from-parser.patch
Patch4: 0004-add-ipset-to-nftables-translation-infrastructure.patch
Patch5: 0005-tests-add-tests-ipset-to-nftables.patch
Patch6: 0006-Fix-typo-in-ipset-translate-man-page.patch
Patch7: 0007-Fix-IPv6-sets-nftables-translation.patch
Patch8: 0008-ipset-translate-allow-invoking-with-a-path-name.patch
Patch9: 0009-Fix-all-debug-mode-warnings.patch
Patch10: 0010-Add-missing-function-to-libipset.map-and-bump-librar.patch
BuildRequires: libmnl-devel
BuildRequires: automake
@ -58,7 +74,7 @@ libraries.
Summary: %{name} service for %{name}s
Requires: %{name} = %{version}-%{release}
BuildRequires: systemd
Requires: iptables-services
Requires: iptables-nft-services
Requires(post): systemd
Requires(preun): systemd
Requires(postun): systemd
@ -100,9 +116,19 @@ install -c -m 644 %{SOURCE1} %{buildroot}/%{_unitdir}
install -d -m 755 %{buildroot}%{_libexecdir}/%{name}
install -c -m 755 %{SOURCE2} %{buildroot}%{_libexecdir}/%{name}
# install ipset-config
install -d -m 755 %{buildroot}%{_sysconfdir}/sysconfig
install -c -m 600 %{SOURCE3} %{buildroot}%{_sysconfdir}/sysconfig/%{name}-config
# install legacy actions for service command
install -d %{buildroot}/%{legacy_actions}/ipset
install -c -m 755 %{SOURCE4} %{buildroot}/%{legacy_actions}/ipset/save
# Create directory for configuration
mkdir -p %{buildroot}%{_sysconfdir}/%{name}
# Turn absolute symlink into a relative one
ln -sf %{name} %{buildroot}/%{_sbindir}/%{name}-translate
%preun
if [[ $1 -eq 0 && -n $(lsmod | grep "^xt_set ") ]]; then
@ -132,7 +158,9 @@ fi
%doc ChangeLog
%license COPYING
%{_mandir}/man8/%{name}.8.*
%{_mandir}/man8/%{name}-translate.8.*
%{_sbindir}/%{name}
%{_sbindir}/%{name}-translate
%files libs
%license COPYING
@ -147,11 +175,48 @@ fi
%files service
%{_unitdir}/%{name}.service
%dir %{_libexecdir}/%{name}
%config(noreplace) %attr(0600,root,root) %{_sysconfdir}/sysconfig/ipset-config
%ghost %config(noreplace) %attr(0600,root,root) %{_sysconfdir}/sysconfig/ipset
%attr(0755,root,root) %{_libexecdir}/%{name}/%{name}.start-stop
%dir %{_sysconfdir}/%{name}
%dir %{legacy_actions}/ipset
%{legacy_actions}/ipset/save
%changelog
* Fri Nov 25 2022 Phil Sutter <psutter@redhat.com> - 7.11-8
- Ship iptables-translate utility with ipset package
- Add missing function to libipset.map and bump library version
- Fix all debug mode warnings
- ipset-translate: allow invoking with a path name
- Fix IPv6 sets nftables translation
- Fix typo in ipset-translate man page
- tests: add tests ipset to nftables
- add ipset to nftables translation infrastructure
- lib: Detach restore routine from parser
- lib: split parser from command execution
* Mon Jan 31 2022 Phil Sutter <psutter@redhat.com> - 7.11-7
- Fix for bad performance restoring large sets which are in use
* Mon Nov 08 2021 Phil Sutter <psutter@redhat.com> - 7.11-6
- Sync ipset.service with RHEL8, fix the required package name
* Mon Aug 09 2021 Mohan Boddu <mboddu@redhat.com> - 7.11-5
- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags
Related: rhbz#1991688
* Fri Jul 02 2021 Phil Sutter <psutter@redhat.com> - 7.11-4
- Improve deprecation notice a bit
* Fri Jun 25 2021 Phil Sutter <psutter@redhat.com> - 7.11-3
- Add deprecation notice to ipset.8
* Fri Apr 16 2021 Mohan Boddu <mboddu@redhat.com> - 7.11-2
- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937
* Mon Mar 01 2021 Nicolas Chauvet <kwizart@gmail.com> - 7.11-1
- Update to 7.11
* Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 7.10-2
- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild

View File

@ -1,209 +1,359 @@
#!/bin/bash
#!/bin/sh
#
# ipset Start and stop ipset firewall sets
#
# config: /etc/ipset/ipset
#
# config: /etc/sysconfig/ipset-config
IPSET=ipset
IPSET_BIN=/usr/sbin/${IPSET}
IPSET_DATA=/etc/${IPSET}/${IPSET}
IPSET_BIN=/usr/sbin/ipset
IPSET_CONFIG=/etc/sysconfig/ipset-config
IPSET_DATA_COMPAT=/etc/sysconfig/ipset
IPSET_DATA_COMPAT_BACKUP=${IPSET_DATA_COMPAT}.save
IPSET_DATA_DIR=/etc/sysconfig/ipset.d
IPSET_DATA_DIR_BACKUP=${IPSET_DATA_DIR}.save
IPSET_DATA_SAVED_FLAG=${IPSET_DATA_DIR}/.saved
IPSET_LOCK=/run/ipset.lock
IPSET_RUN=/run/ipset.run
CLEAN_FILES=""
IPTABLES_CONFIG=/etc/sysconfig/iptables-config
IP6TABLES_CONFIG=${IPTABLES_CONFIG/iptables/ip6tables}
trap "rm -rf \${CLEAN_FILES}" EXIT
TMP_FIFO=/tmp/${IPSET}.$$
if [[ ! -x ${IPSET_BIN} ]]; then
echo "${IPSET_BIN} does not exist."
exit 5
fi
CLEAN_FILES=TMP_FIFO
trap "rm -f \$CLEAN_FILES" EXIT
# Default ipset configuration:
[[ -z $IPSET_SAVE_ON_STOP ]] && IPSET_SAVE_ON_STOP=no # Overridden by ip(6)tables IP(6)TABLES_SAVE_ON_STOP
[[ -z $IPSET_SAVE_ON_RESTART ]] && IPSET_SAVE_ON_RESTART=no # Overridden by ip(6)tables IP(6)TABLES_SAVE_ON_RESTART
# Load iptables configuration(s)
[[ -f "$IPTABLES_CONFIG" ]] && . "$IPTABLES_CONFIG"
[[ -f "$IP6TABLES_CONFIG" ]] && . "$IP6TABLES_CONFIG"
# It doesn't make sense to save iptables config and not our config
[[ ${IPTABLES_SAVE_ON_STOP} = yes || ${IP6TABLES_SAVE_ON_STOP} = yes ]] && IPSET_SAVE_ON_STOP=yes
[[ ${IPTABLES_SAVE_ON_RESTART} = yes || ${IP6TABLES_SAVE_ON_RESTART} = yes ]] && IPSET_SAVE_ON_RESTART=yes
check_can_unload() {
# If the xt_set module is loaded and can't be unloaded, then iptables is
# using ipsets, so refuse to stop the service.
if [[ -n $(lsmod | grep "^xt_set ") ]]; then
rmmod xt_set 2>/dev/null
[[ $? -ne 0 ]] && echo Current iptables configuration requires ipsets && return 1
fi
return 0
info() {
echo "ipset: ${*}" >&2
}
flush_n_delete() {
local ret=0 set
# Flush sets
${IPSET_BIN} flush
let ret+=$?
# Delete ipset sets. If we don't do them individually, then none
# will be deleted unless they all can be.
for set in $(${IPSET_BIN} list -name); do
${IPSET_BIN} destroy 2>/dev/null
[[ $? -ne 0 ]] && ret=1
done
return $ret
warn() {
echo "<4>ipset: ${*}" >&2
}
start_clean()
{
mkfifo -m go= "${TMP_FIFO}"
[[ $? -ne 0 ]] && return 1
# Get the lists of sets in current(old) config and new config
old_sets="$(${IPSET_BIN} list -name | sort -u)"
new_sets="$(grep ^create "${IPSET_DATA}" | cut -d " " -f 2 | sort -u)"
# List of sets no longer wanted
drop_sets="$( printf "%s\n" "${old_sets}" > "${TMP_FIFO}" &
printf "%s\n" "${new_sets}" | comm -23 "${TMP_FIFO}" -
)"
# Get rid of sets no longer needed
# Unfortunately -! doesn't work for destroy, so we have to do it a command at a time
for dset in $drop_sets; do
ipset destroy $dset 2>/dev/null
# If it won't go - ? in use by iptables, just clear it
[[ $? -ne 0 ]] && ipset flush $dset
done
# Now delete the set members no longer required
${IPSET_BIN} save | grep "^add " | sort >${TMP_FIFO} &
grep "^add " ${IPSET_DATA} | sort | comm -23 ${TMP_FIFO} - | sed -e "s/^add /del /" \
| ${IPSET_BIN} restore -!
# At last we can add the set members we haven't got
ipset restore -! <${IPSET_DATA}
rm ${TMP_FIFO}
return 0
err() {
echo "<3>ipset: ${*}" >&2
}
start() {
# Do not start if there is no config file.
[[ ! -f "$IPSET_DATA" ]] && echo "Loaded with no configuration" && return 0
[ -x ${IPSET_BIN} ] || { err "Cannot execute ${IPSET_BIN}"; exit 1; }
# We can skip the first bit and do a simple load if
# there is no current ipset configuration
res=1
if [[ -n $(${IPSET_BIN} list -name) ]]; then
# The following may fail for some bizarre reason
start_clean
res=$?
# Source ipset configuration
# shellcheck source=ipset-config
[ -f ${IPSET_CONFIG} ] && . ${IPSET_CONFIG}
[[ $res -ne 0 ]] && echo "Some old configuration may remain"
fi
set -f
# res -ne 0 => either start_clean failed, or we didn't need to run it
if [[ $res -ne 0 ]]; then
# This is the easy way to start but would leave any old
# entries still configured. Still, better than nothing -
# but fine if we had no config
${IPSET_BIN} restore -! <${IPSET_DATA}
res=$?
fi
if [[ $res -ne 0 ]]; then
return 1
fi
return 0
}
stop() {
# Nothing to stop if ip_set module is not loaded.
lsmod | grep -q "^ip_set "
[[ $? -ne 0 ]] && return 6
flush_n_delete
[[ $? -ne 0 ]] && echo Warning: Not all sets were flushed/deleted
return 0
lock() {
CLEAN_FILES="${CLEAN_FILES} ${IPSET_LOCK}"
until mkdir ${IPSET_LOCK} 2>/dev/null; do :; done
}
save() {
# Do not save if ip_set module is not loaded.
lsmod | grep -q "^ip_set "
[[ $? -ne 0 ]] && return 6
fail=0
[[ -z $(${IPSET_BIN} list -name) ]] && return 0
# Make backups of existing configuration first, if any
[ -d ${IPSET_DATA_DIR} ] && mv -Tf ${IPSET_DATA_DIR} ${IPSET_DATA_DIR_BACKUP}
[ -f ${IPSET_DATA_COMPAT} ] && mv -Tf ${IPSET_DATA_COMPAT} ${IPSET_DATA_COMPAT_BACKUP}
ret=0
TMP_FILE=$(/bin/mktemp -q /tmp/$IPSET.XXXXXX) \
&& CLEAN_FILES+=" $TMP_FILE" \
&& chmod 600 "$TMP_FILE" \
&& ${IPSET_BIN} save > $TMP_FILE 2>/dev/null \
&& [[ -s $TMP_FILE ]] \
|| ret=1
rm -f ${IPSET_DATA_SAVED_FLAG}
if [[ $ret -eq 0 ]]; then
# No need to do anything if the files are the same
if [[ ! -f $IPSET_DATA ]]; then
mv $TMP_FILE $IPSET_DATA && chmod 600 $IPSET_DATA || ret=1
else
diff -q $TMP_FILE $IPSET_DATA >/dev/null
if [[ $? -ne 0 ]]; then
if [[ -f $IPSET_DATA ]]; then
cp -f --preserve=timestamps $IPSET_DATA $IPSET_DATA.save \
&& chmod 600 $IPSET_DATA.save \
|| ret=1
# Save each set in a separate file
mkdir -p ${IPSET_DATA_DIR}
chmod 0700 ${IPSET_DATA_DIR}
IFS="
"
for set in $(${IPSET_BIN} list -n -t); do
# Empty name allowed, use ".set" as suffix. 'ipset save' doesn't
# quote set names with spaces: if we have a space in the name,
# work around this by quoting it ourselves in the output.
# shellcheck disable=SC2003 # No POSIX equivalent to expr index
if expr index "${set}" " " >/dev/null; then
:> "${IPSET_DATA_DIR}/${set}.set"
for line in $(${IPSET_BIN} save "${set}"); do
create=0
echo "${line}" | grep -q "^create " && create=1
if [ $create -eq 1 ]; then
line=${line#create *}
else
line=${line#add *}
fi
line=${line#${set} *}
set="$(echo "${set}" | sed 's/"/\\"/g')"
if [ $create -eq 1 ]; then
echo "create \"${set}\" ${line}" >> "${IPSET_DATA_DIR}/${set}.set"
else
echo "add \"${set}\" ${line}" >> "${IPSET_DATA_DIR}/${set}.set"
fi
done
else
${IPSET_BIN} save "${set}" > "${IPSET_DATA_DIR}/${set}.set" || fail=1
fi
if [[ $ret -eq 0 ]]; then
cp -f --preserve=timestamps $TMP_FILE $IPSET_DATA \
&& chmod 600 $IPSET_DATA \
|| ret=1
fi
fi
fi
fi
[ -f "${IPSET_DATA_DIR}/${set}.set" ] && chmod 600 "${IPSET_DATA_DIR}/${set}.set"
[ $fail -eq 1 ] && err "Cannot save set ${set}" && unset IFS && return 1
done
touch ${IPSET_DATA_SAVED_FLAG} || { unset IFS; return 1; }
unset IFS
rm -f $TMP_FILE
return $ret
# Done: remove backups
rm -rf ${IPSET_DATA_DIR_BACKUP}
rm -rf ${IPSET_DATA_COMPAT_BACKUP}
return 0
}
# Generate a grep regexp matching abbreviated command forms. E.g., for create:
# \(c\|cr\|cre\|crea\|creat\|create\)
cmd_short_expr() {
out=
cmd_len=1
while [ "${cmd_len}" -le "${#1}" ]; do
[ -z "${out}" ] && out='\(' || out="${out}"'\|'
# shellcheck disable=SC2003 # No POSIX equivalent to expr substr
out="${out}$(expr substr "${1}" 1 "${cmd_len}")"
cmd_len=$((cmd_len + 1))
done
echo "${out}"'\)'
}
ipset_restore() {
file="${1}"
retfile="$(mktemp -q /tmp/ipset.XXXXXX)"
CLEAN_FILES="${CLEAN_FILES} ${retfile}"
# If restore fails due to invalid lines, remove them and retry
while ! restore_err="$( (${IPSET_BIN} -f "${file}" -! restore 2>&1; echo $? >"${retfile}") | head -n1; exit "$(cat "${retfile}")" )"; do
warn "${restore_err}"
case ${restore_err#*: } in
"No command specified"*)
line="$(grep -m1 -n "^${restore_err##* }" "${file}")"
line="${line%:*}"
;;
"Missing second mandatory argument to command "*)
cmd="${restore_err##* }"
cmd_expr="$(cmd_short_expr "${cmd}")"
line="$(grep -n '^'"${cmd_expr}" "${file}" | grep -m1 -v '^[0-9]\+\:'"${cmd_expr}"'[[:blank:]]\+[^[:blank:]]\+[[:blank:]]\+[^[:blank:]]\+')"
line="${line%:*}"
;;
"Missing mandatory argument to command "*)
cmd="${restore_err##* }"
cmd_expr="$(cmd_short_expr "${cmd}")"
line="$(grep -n '^'"${cmd_expr}" "${file}" | grep -m1 -v '^[0-9]\+\:'"${cmd_expr}"'[[:blank:]]\+[^[:blank:]]\+')"
line="${line%:*}"
;;
"Command "*"is invalid in restore mode"*)
restore_err_cmd="${restore_err#*: }"
restore_err_cmd="${restore_err_cmd#*\`}"
restore_err_cmd="${restore_err_cmd%%\'*}"
cmd="${restore_err_cmd##* }"
cmd_expr="$(cmd_short_expr "${cmd}")"
line="$(grep -m1 -ne '^'"${cmd_expr}"'[[:blank:]]\+' -e '^'"${restore_err_cmd}"'$' "${file}")"
line="${line%:*}"
;;
"Error in line "*)
line="${restore_err%: *}"
line="${line##* }"
;;
*)
rm "${retfile}"
CLEAN_FILES="${CLEAN_FILES%* ${retfile}}"
return 1
;;
esac
[ -z "${line}" ] && return 1
warn "Skipped invalid entry: $(sed "${line}q;d" "${file}")"
sed -i -e "${line}d" "${file}"
[ -s "${file}" ] || return 1
done
rm "${retfile}"
CLEAN_FILES="${CLEAN_FILES%* ${retfile}}"
}
load() {
if [ -f ${IPSET_DATA_SAVED_FLAG} ]; then
# If we have a cleanly saved directory with all sets, we can
# delete any left-overs and use it
rm -rf ${IPSET_DATA_DIR_BACKUP}
rm -f ${IPSET_DATA_COMPAT_BACKUP}
else
# If sets weren't cleanly saved, restore from backups
[ -d ${IPSET_DATA_DIR_BACKUP} ] && rm -rf ${IPSET_DATA_DIR} && mv -Tf ${IPSET_DATA_DIR_BACKUP} ${IPSET_DATA_DIR}
[ -f ${IPSET_DATA_COMPAT_BACKUP} ] && rm -f ${IPSET_DATA_COMPAT} && mv -Tf ${IPSET_DATA_COMPAT_BACKUP} ${IPSET_DATA_COMPAT}
fi
if [ ! -d ${IPSET_DATA_DIR} ] && [ ! -f ${IPSET_DATA_COMPAT} ]; then
info "No existing configuration available, none loaded"
touch ${IPSET_RUN}
return
fi
# Merge all sets into temporary file
merged="$(mktemp -q /tmp/ipset.XXXXXX)"
CLEAN_FILES="${CLEAN_FILES} ${merged}"
chmod 600 "${merged}"
set +f
if [ -d ${IPSET_DATA_DIR} ]; then
# Copy create commands from each saved set first, then the rest:
# list:set entries depend on other sets, so make sure they all
# get created first
for f in "${IPSET_DATA_DIR}"/*; do
[ "${f}" = "${IPSET_DATA_DIR}/*" ] && break
[ -f "${f}" ] || continue
grep '^c' "${f}" >> "${merged}"
done
for f in "${IPSET_DATA_DIR}"/*; do
[ "${f}" = "${IPSET_DATA_DIR}/*" ] && break
[ -f "${f}" ] || continue
grep -v '^c' "${f}" >> "${merged}"
done
fi
set -f
[ -f ${IPSET_DATA_COMPAT} ] && cat ${IPSET_DATA_COMPAT} >> "${merged}"
# Drop sets that aren't in saved data, mark conflicts with existing sets
conflicts=""
IFS="
"
for set in $(${IPSET_BIN} list -n -t); do
grep -q "^create ${set} " "${merged}" && conflicts="${conflicts}|${set}" && continue
# We can't destroy the set if it's in use, flush it instead
if ! ${IPSET_BIN} destroy "${set}" 2>/dev/null; then
${IPSET_BIN} flush "${set}"
fi
done
unset IFS
conflicts="${conflicts#|*}"
# Common case: if we have no conflicts, just restore in one shot
if [ -z "${conflicts}" ]; then
if ! ipset_restore "${merged}"; then
err "Failed to restore configured sets"
exit 1
fi
rm "${merged}"
CLEAN_FILES="${CLEAN_FILES%* ${merged}}"
touch ${IPSET_RUN}
return
fi
# Find a salt for md5sum that makes names of saved sets unique
salt=0
while true; do
unique=1
IFS="
"
for set in $(${IPSET_BIN} list -n -t); do
if grep -q "^create $(echo "${salt}${set}" | md5sum | head -c31) " "${merged}"; then
unique=0
break
fi
done
unset IFS
[ ${unique} -eq 1 ] && break
salt=$((salt + 1))
done
# Add sets, mangling names for conflicting sets
mangled="$(mktemp -q /tmp/ipset.XXXXXX)"
CLEAN_FILES="${CLEAN_FILES} ${mangled}"
chmod 600 "${mangled}"
cat "${merged}" > "${mangled}"
IFS='|'
for set in ${conflicts}; do
new_name=$(echo "${salt}${set}" | md5sum | head -c31)
echo "s/^(add|create) $set /\1 $new_name /"
done | sed -i -r -f - "${mangled}"
unset IFS
if ! ipset_restore "${mangled}"; then
err "Failed to restore configured sets"
exit 1
fi
rm "${mangled}"
CLEAN_FILES="${CLEAN_FILES%* ${mangled}}"
# Swap and delete old sets
IFS='|'
for set in ${conflicts}; do
mangled="$(echo "${salt}${set}" | md5sum | head -c31)"
if ! ${IPSET_BIN} swap "${set}" "${mangled}" 2>/dev/null; then
# This fails if set types are different: try to destroy
# existing set
if ! ${IPSET_BIN} destroy "${set}" 2>/dev/null; then
# Conflicting set is in use, we can only warn
# and flush the existing set
err "Cannot load set \"${set}\", set with same name and conflicting type in use"
${IPSET_BIN} flush "${set}"
${IPSET_BIN} destroy "${mangled}"
else
${IPSET_BIN} rename "${mangled}" "${set}"
fi
else
${IPSET_BIN} destroy "${mangled}"
fi
done
unset IFS
rm "${merged}"
CLEAN_FILES="${CLEAN_FILES%* ${merged}}"
touch ${IPSET_RUN}
}
cleanup() {
${IPSET_BIN} flush || err "Failed to flush sets"
# Try to destroy all sets at once. This will fail if some are in use,
# destroy all the other ones in that case
${IPSET_BIN} destroy 2>/dev/null && return
IFS="
"
for set in $(${IPSET_BIN} list -n -t); do
if ! ${IPSET_BIN} destroy "${set}"; then
err "Failed to destroy set ${set}"
fi
done
unset IFS
}
stop() {
[ -f ${IPSET_RUN} ] || { info "Not running"; return 0; }
[ "${IPSET_SAVE_ON_STOP}" = "yes" ] && { save || err "Failed to save sets"; }
# Nothing to stop if the ip_set module is not loaded
lsmod | grep -q "^ip_set " || { info "Not running"; rm ${IPSET_RUN}; return 0; }
# If the xt_set module is in use, then iptables is using ipset, so
# refuse to stop the service
if mod="$(lsmod | grep ^xt_set)"; then
if [ "$(echo "${mod}" | tr -s ' ' | cut -d' ' -f3)" != "0" ]; then
err "Current iptables configuration requires ipset" && return 1
fi
fi
cleanup
rm ${IPSET_RUN}
return 0
}
lock
case "$1" in
start)
start
RETVAL=$?
start)
load
;;
stop)
check_can_unload || exit 1
[[ $IPSET_SAVE_ON_STOP = yes ]] && save
stop)
stop
RETVAL=$?
[[ $RETVAL -eq 6 ]] && echo "${IPSET}: not running" && exit 0
;;
reload)
[[ $IPSET_SAVE_ON_RESTART = yes ]] && save
stop
RETVAL=$?
[[ $RETVAL -eq 6 ]] && echo "${IPSET}: not running" && exit 0
start
RETVAL=$?
reload)
cleanup
load
;;
*)
echo "Usage: $IPSET {start|stop|reload}" >&2
save)
save
;;
*)
info "Usage: $0 {start|stop|reload|save}"
exit 1
esac
exit $RETVAL
exit $?

6
rpminspect.yaml Normal file
View File

@ -0,0 +1,6 @@
badfuncs:
allowed:
/usr/lib*/libipset.so.*:
# Upstream maintainer deliberately chose this over getaddrinfo, see
# commit c52cf6000923b ("Use gethostbyname2 instead of getaddrinfo")
- gethostbyname2

View File

@ -1 +1 @@
SHA512 (ipset-7.10.tar.bz2) = 7f45c46f8c158600b1e64354500f31e7fb3c8ee844d55eab9f7eec298eecc27c9cb89e24a8ec6c180665dd0cc29776a9e42ada796b3e87d034cc39cdd4665807
SHA512 (ipset-7.11.tar.bz2) = 20890de32c17c04d9d3ae42fff64acfe21a252974bee5843ae39bdda707fcef55fde11cffccab9f987bf7e18f5445443c46c50eb854fb6f93f172f7bad07f922