]> git.ipfire.org Git - thirdparty/ipset.git/commitdiff
Restore mode did not work for IPv6 (reported by Elie Rosenblum)
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Wed, 22 Dec 2010 09:43:05 +0000 (10:43 +0100)
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Wed, 22 Dec 2010 09:43:05 +0000 (10:43 +0100)
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.

lib/session.c
lib/types.c

index 5d341ab96ae7d214aae32b9a2ca8fc90da26bd1f..4a08b94ddf4638b9970e58226e0454d9cfc64208 100644 (file)
@@ -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);
index 1bd4274d1f4fcfe4fe463cc65f4844eef9e76bbb..69dac6aa3491543087668dccbf4ea05704cea869 100644 (file)
@@ -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);