summaryrefslogtreecommitdiffstats
path: root/lib
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 /lib
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.
Diffstat (limited to 'lib')
-rw-r--r--lib/ipset.c4
-rw-r--r--lib/session.c25
2 files changed, 22 insertions, 7 deletions
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;