summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2010-12-22 10:43:05 +0100
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2010-12-22 10:43:05 +0100
commitd794a110478866311416bf73e2a5239253aead40 (patch)
tree23871d60f4fad0cfc5f531cce59e6adae9be92f2 /lib
parentcffe9a53f6bacb0c72d83efa19b1a9764d44dc72 (diff)
Restore mode did not work for IPv6 (reported by Elie Rosenblum)
The set cache stored the default family (INET) instead of the set family, therefore restore mode for IPv6 did not work. The set cache fixed and message aggregation reworked.
Diffstat (limited to 'lib')
-rw-r--r--lib/session.c36
-rw-r--r--lib/types.c15
2 files changed, 30 insertions, 21 deletions
diff --git a/lib/session.c b/lib/session.c
index 5d341ab..4a08b94 100644
--- a/lib/session.c
+++ b/lib/session.c
@@ -1510,12 +1510,12 @@ build_send_private_msg(struct ipset_session *session, enum ipset_cmd cmd)
}
static inline bool
-may_aggregate_ad(struct ipset_session *session, struct ipset_data *data,
- enum ipset_cmd cmd)
+may_aggregate_ad(struct ipset_session *session, enum ipset_cmd cmd)
{
- return (cmd == IPSET_CMD_ADD || cmd == IPSET_CMD_DEL)
+ return session->lineno != 0
+ && (cmd == IPSET_CMD_ADD || cmd == IPSET_CMD_DEL)
&& cmd == session->cmd
- && STREQ(ipset_data_setname(data), session->saved_setname);
+ && STREQ(ipset_data_setname(session->data), session->saved_setname);
}
static int
@@ -1693,7 +1693,8 @@ ipset_commit(struct ipset_session *session)
session->buffer,
session->bufsize);
- /* Reset data block and nested state */
+ /* Reset saved data and nested state */
+ session->saved_setname[0] = '\0';
for (i = session->nestid - 1; i >= 0; i--)
session->nested[i] = NULL;
session->nestid = 0;
@@ -1771,8 +1772,13 @@ ipset_cmd(struct ipset_session *session, enum ipset_cmd cmd, uint32_t lineno)
return build_send_private_msg(session, cmd);
/* Check aggregatable commands */
- if (session->lineno != 0)
- aggregate = may_aggregate_ad(session, data, cmd);
+ aggregate = may_aggregate_ad(session, cmd);
+ if (!aggregate) {
+ /* Flush possible aggregated commands */
+ ret = ipset_commit(session);
+ if (ret < 0)
+ return ret;
+ }
/* Real command: update lineno too */
session->cmd = cmd;
@@ -1793,7 +1799,8 @@ ipset_cmd(struct ipset_session *session, enum ipset_cmd cmd, uint32_t lineno)
D("build_msg returned %u", ret);
if (ret > 0) {
/* Buffer is full, send buffered commands */
- if (ipset_commit(session) < 0)
+ ret = ipset_commit(session);
+ if (ret < 0)
goto cleanup;
ret = build_msg(session, false);
D("build_msg 2 returned %u", ret);
@@ -1804,16 +1811,19 @@ ipset_cmd(struct ipset_session *session, enum ipset_cmd cmd, uint32_t lineno)
/* We have to save the type for error handling */
session->saved_type = ipset_data_get(data, IPSET_OPT_TYPE);
- /* Save setname for the next possible aggregated restore line */
if (session->lineno != 0
&& (cmd == IPSET_CMD_ADD || cmd == IPSET_CMD_DEL)) {
+ /* Save setname for the next possible aggregated restore line */
strcpy(session->saved_setname, ipset_data_setname(data));
- ret = 0;
+ ipset_data_reset(data);
/* Don't commit: we may aggregate next command */
- } else {
- D("call commit");
- ret = ipset_commit(session);
+ ret = 0;
+ goto cleanup;
}
+
+ D("call commit");
+ ret = ipset_commit(session);
+
cleanup:
D("reset data");
ipset_data_reset(data);
diff --git a/lib/types.c b/lib/types.c
index 1bd4274..69dac6a 100644
--- a/lib/types.c
+++ b/lib/types.c
@@ -276,10 +276,9 @@ found:
}
#define set_family_and_type(data, match, family) do { \
- if (family == AF_UNSPEC && match->family != AF_UNSPEC) { \
+ if (family == AF_UNSPEC && match->family != AF_UNSPEC) \
family = match->family == AF_INET46 ? AF_INET : match->family;\
- ipset_data_set(data, IPSET_OPT_FAMILY, &family);\
- } \
+ ipset_data_set(data, IPSET_OPT_FAMILY, &family); \
ipset_data_set(data, IPSET_OPT_TYPE, match); \
} while (0)
@@ -293,7 +292,7 @@ adt_type_get(struct ipset_session *session)
const struct ipset_type *match;
const char *setname, *typename;
const uint8_t *revision;
- uint8_t family;
+ uint8_t family = AF_UNSPEC;
int ret;
data = ipset_session_data(session);
@@ -304,8 +303,9 @@ adt_type_get(struct ipset_session *session)
/* Check existing sets in cache */
for (s = setlist; s != NULL; s = s->next) {
if (STREQ(setname, s->name)) {
- match = s->type;
- goto found;
+ ipset_data_set(data, IPSET_OPT_FAMILY, &s->family);
+ ipset_data_set(data, IPSET_OPT_TYPE, s->type);
+ return s->type;
}
}
@@ -342,7 +342,6 @@ adt_type_get(struct ipset_session *session)
family == AF_INET6 ? "inet6" : "unspec",
*revision);
-found:
set_family_and_type(data, match, family);
return match;
@@ -396,7 +395,7 @@ ipset_type_check(struct ipset_session *session)
const struct ipset_type *t, *match = NULL;
struct ipset_data *data;
const char *typename;
- uint8_t family, revision;
+ uint8_t family = AF_UNSPEC, revision;
assert(session);
data = ipset_session_data(session);