summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2018-10-22 20:01:14 +0200
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2018-10-22 20:01:14 +0200
commitb934ebcd368ebf4d2dd0bf4edabb083fdac82dad (patch)
treeba48c183fe9d244ebf13a418e3e8a22a1ee8c5fc
parentc387170f903a976922de970042f8fdb6ec93a0f8 (diff)
Prepare the ipset tool to handle multiple protocol versions
From now on the "version" command asks the kernel protocol version too and reports if the userspace - kernel protocols do not match.
-rw-r--r--include/libipset/linux_ip_set.h5
-rw-r--r--lib/ipset.c4
-rw-r--r--lib/session.c25
3 files changed, 25 insertions, 9 deletions
diff --git a/include/libipset/linux_ip_set.h b/include/libipset/linux_ip_set.h
index 883922d..2096611 100644
--- a/include/libipset/linux_ip_set.h
+++ b/include/libipset/linux_ip_set.h
@@ -12,8 +12,9 @@
#include <linux/types.h>
-/* The protocol version */
-#define IPSET_PROTOCOL 6
+/* The supported protocol versions */
+#define IPSET_PROTOCOL_MIN 6
+#define IPSET_PROTOCOL 7
/* The max length of strings including NUL: set and type identifiers */
#define IPSET_MAXNAMELEN 32
diff --git a/lib/ipset.c b/lib/ipset.c
index 70189f9..8d05b39 100644
--- a/lib/ipset.c
+++ b/lib/ipset.c
@@ -1090,6 +1090,10 @@ ipset_parse_argv(struct ipset *ipset, int oargc, char *oargv[])
return 0;
printf("%s v%s, protocol version: %u\n",
program_name, program_version, IPSET_PROTOCOL);
+ /* Check kernel protocol version */
+ ipset_cmd(session, IPSET_CMD_NONE, 0);
+ if (ipset_session_report_type(session) != IPSET_NO_ERROR)
+ ipset->standard_error(ipset, p);
if (ipset->interactive)
return 0;
return ipset->custom_error(ipset, p, IPSET_NO_PROBLEM, NULL);
diff --git a/lib/session.c b/lib/session.c
index a5a93da..c19191a 100644
--- a/lib/session.c
+++ b/lib/session.c
@@ -44,6 +44,7 @@ struct ipset_session {
const struct ipset_type *saved_type; /* Saved type */
struct nlattr *nested[IPSET_NEST_MAX]; /* Pointer to nest levels */
uint8_t nestid; /* Current nest level */
+ uint8_t protocol; /* The protocol used */
bool version_checked; /* Version checked */
/* Output buffer */
char outbuf[IPSET_OUTBUFLEN]; /* Output buffer */
@@ -1170,6 +1171,7 @@ callback_version(struct ipset_session *session, struct nlattr *nla[])
"while userspace supports protocol versions %u-%u",
min, max, IPSET_PROTOCOL_MIN, IPSET_PROTOCOL_MAX);
+ session->protocol = MIN(max, IPSET_PROTOCOL_MAX);
session->version_checked = true;
return MNL_CB_STOP;
@@ -1297,10 +1299,10 @@ callback_data(const struct nlmsghdr *nlh, void *data)
proto = mnl_attr_get_u8(nla[IPSET_ATTR_PROTOCOL]);
/* Check protocol */
- if (cmd != IPSET_CMD_PROTOCOL && proto != IPSET_PROTOCOL)
+ if (cmd != IPSET_CMD_PROTOCOL && proto != session->protocol)
FAILURE("Giving up: kernel protocol version %u "
"does not match our protocol version %u",
- proto, IPSET_PROTOCOL);
+ proto, session->protocol);
D("Message: %s", cmd2name[cmd]);
switch (cmd) {
@@ -1602,8 +1604,8 @@ data2attr(struct ipset_session *session, struct nlmsghdr *nlh,
type, family, attrs);
}
-#define ADDATTR_PROTOCOL(nlh) \
- mnl_attr_put_u8(nlh, IPSET_ATTR_PROTOCOL, IPSET_PROTOCOL)
+#define ADDATTR_PROTOCOL(nlh, protocol) \
+ mnl_attr_put_u8(nlh, IPSET_ATTR_PROTOCOL, protocol)
#define ADDATTR(session, nlh, data, type, family, attrs) \
data2attr(session, nlh, data, type, family, attrs)
@@ -1655,7 +1657,8 @@ build_send_private_msg(struct ipset_session *session, enum ipset_cmd cmd)
/* Initialize header */
session->transport->fill_hdr(session->handle, cmd, buffer, len, 0);
- ADDATTR_PROTOCOL(nlh);
+ ADDATTR_PROTOCOL(nlh,
+ cmd == IPSET_CMD_PROTOCOL ? IPSET_PROTOCOL : session->protocol);
switch (cmd) {
case IPSET_CMD_PROTOCOL:
@@ -1719,7 +1722,7 @@ build_msg(struct ipset_session *session, bool aggregate)
session->buffer,
session->bufsize,
session->envopts);
- ADDATTR_PROTOCOL(nlh);
+ ADDATTR_PROTOCOL(nlh, session->protocol);
}
D("Protocol added, aggregate %s", aggregate ? "yes" : "no");
switch (session->cmd) {
@@ -1965,7 +1968,7 @@ ipset_cmd(struct ipset_session *session, enum ipset_cmd cmd, uint32_t lineno)
assert(session);
- if (cmd <= IPSET_CMD_NONE || cmd >= IPSET_MSG_MAX)
+ if (cmd < IPSET_CMD_NONE || cmd >= IPSET_MSG_MAX)
return 0;
/* Initialize transport method if not done yet */
@@ -1979,7 +1982,14 @@ ipset_cmd(struct ipset_session *session, enum ipset_cmd cmd, uint32_t lineno)
if (!session->version_checked) {
if (build_send_private_msg(session, IPSET_CMD_PROTOCOL) < 0)
return -1;
+ if (ipset_session_report_type(session) == IPSET_WARNING &&
+ cmd != IPSET_CMD_NONE)
+ /* Suppress protocol warning */
+ ipset_session_report_reset(session);
}
+ /* IPSET_CMD_NONE: check protocol version only */
+ if (cmd == IPSET_CMD_NONE)
+ return 0;
/* Private commands */
if (cmd == IPSET_CMD_TYPE || cmd == IPSET_CMD_HEADER)
@@ -2111,6 +2121,7 @@ ipset_session_init(ipset_print_outfn print_outfn, void *p)
session->buffer = session + 1;
session->istream = stdin;
session->ostream = stdout;
+ session->protocol = IPSET_PROTOCOL;
/* The single transport method yet */
session->transport = &ipset_mnl_transport;