extern void ipset_data_flags_set(struct ipset_data *data, uint64_t flags);
extern void ipset_data_flags_unset(struct ipset_data *data, uint64_t flags);
extern bool ipset_data_ignored(struct ipset_data *data, enum ipset_opt opt);
+extern bool ipset_data_test_ignored(struct ipset_data *data, enum ipset_opt opt);
extern int ipset_data_set(struct ipset_data *data, enum ipset_opt opt,
const void *value);
* @data: data blob
* @flags: the option flag to be ignored
*
- * Returns true if the option was not already ignored.
+ * Returns true if the option was already ignored.
*/
bool
ipset_data_ignored(struct ipset_data *data, enum ipset_opt opt)
return ignored;
}
+/**
+ * ipset_data_test_ignored - test ignored bits in the data blob
+ * @data: data blob
+ * @flags: the option flag to be tested
+ *
+ * Returns true if the option is ignored.
+ */
+bool
+ipset_data_test_ignored(struct ipset_data *data, enum ipset_opt opt)
+{
+ assert(data);
+
+ return data->ignored & IPSET_FLAG(opt);
+}
+
/**
* ipset_data_set - put data into the data blob
* @data: data blob
break;
case IPSET_OPT_FAMILY:
data->family = *(const uint8_t *) value;
+ data->ignored &= ~IPSET_FLAG(IPSET_OPT_FAMILY);
D("family set to %u", data->family);
break;
/* CADT options */
ipset_load_types;
ipset_port_usage;
ipset_parse_timeout;
+ ipset_data_test_ignored;
} LIBIPSET_1.0;
assert(str);
data = ipset_session_data(session);
- if (ipset_data_flags_test(data, IPSET_FLAG(IPSET_OPT_FAMILY)))
+ if (ipset_data_flags_test(data, IPSET_FLAG(IPSET_OPT_FAMILY))
+ && !ipset_data_test_ignored(data, IPSET_OPT_FAMILY))
syntax_err("protocol family may not be specified "
"multiple times");
const struct ipset_arg *arg,
const char *str)
{
- if (ipset_data_flags_test(ipset_session_data(session),
- IPSET_FLAG(arg->opt)))
+ struct ipset_data *data = ipset_session_data(session);
+
+ if (ipset_data_flags_test(data, IPSET_FLAG(arg->opt))
+ && !(arg->opt == IPSET_OPT_FAMILY
+ && ipset_data_test_ignored(data, IPSET_OPT_FAMILY)))
syntax_err("%s already specified", arg->name[0]);
return arg->parse(session, arg->opt, str);
uint8_t family, tmin = 0, tmax = 0;
uint8_t kmin, kmax;
int ret;
+ bool ignore_family = false;
data = ipset_session_data(session);
assert(data);
family = match->family == NFPROTO_IPSET_IPV46 ?
NFPROTO_IPV4 : match->family;
ipset_data_set(data, IPSET_OPT_FAMILY, &family);
+ if (match->family == NFPROTO_IPSET_IPV46)
+ ignore_family = true;
}
if (match->kernel_check == IPSET_KERNEL_OK)
found:
ipset_data_set(data, IPSET_OPT_TYPE, match);
+ if (ignore_family) {
+ /* Overload ignored flag */
+ D("set ignored flag to FAMILY");
+ ipset_data_ignored(data, IPSET_OPT_FAMILY);
+ }
return match;
}
switch (cmd) {
case IPSET_CMD_CREATE:
- return create_type_get(session);
+ return ipset_data_test(ipset_session_data(session),
+ IPSET_OPT_TYPE)
+ ? ipset_data_get(ipset_session_data(session),
+ IPSET_OPT_TYPE)
+ : create_type_get(session);
case IPSET_CMD_ADD:
case IPSET_CMD_DEL:
case IPSET_CMD_TEST: