mirror of
git://git.code.sf.net/p/xtables-addons/xtables-addons
synced 2025-09-22 04:24:58 +02:00
ipset: update to 6.6a-genl
This commit is contained in:
@@ -66,6 +66,7 @@ struct ipset_data {
|
||||
/* ADT/LIST/SAVE */
|
||||
struct {
|
||||
union nf_inet_addr ip2;
|
||||
union nf_inet_addr ip2_to;
|
||||
uint8_t cidr2;
|
||||
uint8_t proto;
|
||||
char ether[ETH_ALEN];
|
||||
@@ -289,6 +290,11 @@ ipset_data_set(struct ipset_data *data, enum ipset_opt opt, const void *value)
|
||||
return -1;
|
||||
copy_addr(data->family, &data->adt.ip2, value);
|
||||
break;
|
||||
case IPSET_OPT_IP2_TO:
|
||||
if (!(data->family == AF_INET || data->family == AF_INET6))
|
||||
return -1;
|
||||
copy_addr(data->family, &data->adt.ip2_to, value);
|
||||
break;
|
||||
case IPSET_OPT_CIDR2:
|
||||
data->adt.cidr2 = *(const uint8_t *) value;
|
||||
break;
|
||||
@@ -401,6 +407,8 @@ ipset_data_get(const struct ipset_data *data, enum ipset_opt opt)
|
||||
return data->adt.nameref;
|
||||
case IPSET_OPT_IP2:
|
||||
return &data->adt.ip2;
|
||||
case IPSET_OPT_IP2_TO:
|
||||
return &data->adt.ip2_to;
|
||||
case IPSET_OPT_CIDR2:
|
||||
return &data->adt.cidr2;
|
||||
case IPSET_OPT_PROTO:
|
||||
@@ -436,6 +444,7 @@ ipset_data_sizeof(enum ipset_opt opt, uint8_t family)
|
||||
case IPSET_OPT_IP:
|
||||
case IPSET_OPT_IP_TO:
|
||||
case IPSET_OPT_IP2:
|
||||
case IPSET_OPT_IP2_TO:
|
||||
return family == AF_INET ? sizeof(uint32_t)
|
||||
: sizeof(struct in6_addr);
|
||||
case IPSET_OPT_PORT:
|
||||
|
268
extensions/ipset-6/libipset/debug.c
Normal file
268
extensions/ipset-6/libipset/debug.c
Normal file
@@ -0,0 +1,268 @@
|
||||
/* Copyright 2011 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <arpa/inet.h> /* inet_ntop */
|
||||
#include <libmnl/libmnl.h> /* libmnl backend */
|
||||
|
||||
struct ipset_attrname {
|
||||
const char *name;
|
||||
};
|
||||
|
||||
static const struct ipset_attrname cmdattr2name[] = {
|
||||
[IPSET_ATTR_PROTOCOL] = { .name = "PROTOCOL" },
|
||||
[IPSET_ATTR_SETNAME] = { .name = "SETNAME" },
|
||||
[IPSET_ATTR_TYPENAME] = { .name = "TYPENAME" },
|
||||
[IPSET_ATTR_REVISION] = { .name = "REVISION" },
|
||||
[IPSET_ATTR_FAMILY] = { .name = "FAMILY" },
|
||||
[IPSET_ATTR_FLAGS] = { .name = "FLAGS" },
|
||||
[IPSET_ATTR_DATA] = { .name = "DATA" },
|
||||
[IPSET_ATTR_ADT] = { .name = "ADT" },
|
||||
[IPSET_ATTR_LINENO] = { .name = "LINENO" },
|
||||
[IPSET_ATTR_PROTOCOL_MIN] = { .name = "PROTO_MIN" },
|
||||
};
|
||||
|
||||
static const struct ipset_attrname createattr2name[] = {
|
||||
[IPSET_ATTR_IP] = { .name = "IP" },
|
||||
[IPSET_ATTR_IP_TO] = { .name = "IP_TO" },
|
||||
[IPSET_ATTR_CIDR] = { .name = "CIDR" },
|
||||
[IPSET_ATTR_PORT] = { .name = "PORT" },
|
||||
[IPSET_ATTR_PORT_TO] = { .name = "PORT_TO" },
|
||||
[IPSET_ATTR_TIMEOUT] = { .name = "TIMEOUT" },
|
||||
[IPSET_ATTR_PROTO] = { .name = "PROTO" },
|
||||
[IPSET_ATTR_CADT_FLAGS] = { .name = "CADT_FLAGS" },
|
||||
[IPSET_ATTR_CADT_LINENO] = { .name = "CADT_LINENO" },
|
||||
[IPSET_ATTR_GC] = { .name = "GC" },
|
||||
[IPSET_ATTR_HASHSIZE] = { .name = "HASHSIZE" },
|
||||
[IPSET_ATTR_MAXELEM] = { .name = "MAXELEM" },
|
||||
[IPSET_ATTR_NETMASK] = { .name = "NETMASK" },
|
||||
[IPSET_ATTR_PROBES] = { .name = "PROBES" },
|
||||
[IPSET_ATTR_RESIZE] = { .name = "RESIZE" },
|
||||
[IPSET_ATTR_SIZE] = { .name = "SIZE" },
|
||||
[IPSET_ATTR_ELEMENTS] = { .name = "ELEMENTS" },
|
||||
[IPSET_ATTR_REFERENCES] = { .name = "REFERENCES" },
|
||||
[IPSET_ATTR_MEMSIZE] = { .name = "MEMSIZE" },
|
||||
};
|
||||
|
||||
static const struct ipset_attrname adtattr2name[] = {
|
||||
[IPSET_ATTR_IP] = { .name = "IP" },
|
||||
[IPSET_ATTR_IP_TO] = { .name = "IP_TO" },
|
||||
[IPSET_ATTR_CIDR] = { .name = "CIDR" },
|
||||
[IPSET_ATTR_PORT] = { .name = "PORT" },
|
||||
[IPSET_ATTR_PORT_TO] = { .name = "PORT_TO" },
|
||||
[IPSET_ATTR_TIMEOUT] = { .name = "TIMEOUT" },
|
||||
[IPSET_ATTR_PROTO] = { .name = "PROTO" },
|
||||
[IPSET_ATTR_CADT_FLAGS] = { .name = "CADT_FLAGS" },
|
||||
[IPSET_ATTR_CADT_LINENO] = { .name = "CADT_LINENO" },
|
||||
[IPSET_ATTR_ETHER] = { .name = "ETHER" },
|
||||
[IPSET_ATTR_NAME] = { .name = "NAME" },
|
||||
[IPSET_ATTR_NAMEREF] = { .name = "NAMEREF" },
|
||||
[IPSET_ATTR_IP2] = { .name = "IP2" },
|
||||
[IPSET_ATTR_CIDR2] = { .name = "CIDR2" },
|
||||
[IPSET_ATTR_IP2_TO] = { .name = "IP2_TO" },
|
||||
};
|
||||
|
||||
static void
|
||||
debug_cadt_attrs(int max, const struct ipset_attr_policy *policy,
|
||||
const struct ipset_attrname attr2name[],
|
||||
struct nlattr *nla[])
|
||||
{
|
||||
uint32_t v;
|
||||
int i;
|
||||
|
||||
fprintf(stderr,"\t\t%s attributes:\n", policy == create_attrs ? "CREATE" : "ADT");
|
||||
for (i = IPSET_ATTR_UNSPEC + 1; i <= max; i++) {
|
||||
if (!nla[i])
|
||||
continue;
|
||||
switch (policy[i].type) {
|
||||
case MNL_TYPE_U8:
|
||||
v = * (uint8_t *) mnl_attr_get_payload(nla[i]);
|
||||
fprintf(stderr, "\t\t%s: %u\n",
|
||||
attr2name[i].name, v);
|
||||
break;
|
||||
case MNL_TYPE_U16:
|
||||
v = * (uint16_t *) mnl_attr_get_payload(nla[i]);
|
||||
fprintf(stderr, "\t\t%s: %u\n",
|
||||
attr2name[i].name, ntohs(v));
|
||||
break;
|
||||
case MNL_TYPE_U32:
|
||||
v = * (uint32_t *) mnl_attr_get_payload(nla[i]);
|
||||
fprintf(stderr, "\t\t%s: %u\n",
|
||||
attr2name[i].name, ntohl(v));
|
||||
break;
|
||||
case MNL_TYPE_NUL_STRING:
|
||||
fprintf(stderr, "\t\t%s: %s\n",
|
||||
attr2name[i].name,
|
||||
(const char *) mnl_attr_get_payload(nla[i]));
|
||||
break;
|
||||
case MNL_TYPE_NESTED: {
|
||||
struct nlattr *ipattr[IPSET_ATTR_IPADDR_MAX+1] = {};
|
||||
char addr[INET6_ADDRSTRLEN];
|
||||
void *d;
|
||||
|
||||
if (mnl_attr_parse_nested(nla[i], ipaddr_attr_cb, ipattr) < 0) {
|
||||
fprintf(stderr, "\t\tIPADDR: cannot validate and parse attributes\n");
|
||||
continue;
|
||||
}
|
||||
if (ipattr[IPSET_ATTR_IPADDR_IPV4]) {
|
||||
d = mnl_attr_get_payload(ipattr[IPSET_ATTR_IPADDR_IPV4]);
|
||||
|
||||
inet_ntop(AF_INET, d, addr, INET6_ADDRSTRLEN);
|
||||
fprintf(stderr, "\t\t%s: %s\n",
|
||||
attr2name[i].name, addr);
|
||||
} else if (ipattr[IPSET_ATTR_IPADDR_IPV6]) {
|
||||
d = mnl_attr_get_payload(ipattr[IPSET_ATTR_IPADDR_IPV6]);
|
||||
|
||||
inet_ntop(AF_INET6, d, addr, INET6_ADDRSTRLEN);
|
||||
fprintf(stderr, "\t\t%s: %s\n",
|
||||
attr2name[i].name, addr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
fprintf(stderr, "\t\t%s: unresolved!\n",
|
||||
attr2name[i].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
debug_cmd_attrs(int cmd, struct nlattr *nla[])
|
||||
{
|
||||
struct nlattr *adt[IPSET_ATTR_ADT_MAX+1] = {};
|
||||
struct nlattr *cattr[IPSET_ATTR_CREATE_MAX+1] = {};
|
||||
uint32_t v;
|
||||
int i;
|
||||
|
||||
fprintf(stderr,"\tCommand attributes:\n");
|
||||
for (i = IPSET_ATTR_UNSPEC + 1; i <= IPSET_ATTR_CMD_MAX; i++) {
|
||||
if (!nla[i])
|
||||
continue;
|
||||
switch (cmd_attrs[i].type) {
|
||||
case MNL_TYPE_U8:
|
||||
v = * (uint8_t *) mnl_attr_get_payload(nla[i]);
|
||||
fprintf(stderr, "\t%s: %u\n",
|
||||
cmdattr2name[i].name, v);
|
||||
break;
|
||||
case MNL_TYPE_U16:
|
||||
v = * (uint16_t *) mnl_attr_get_payload(nla[i]);
|
||||
fprintf(stderr, "\t%s: %u\n",
|
||||
cmdattr2name[i].name, ntohs(v));
|
||||
break;
|
||||
case MNL_TYPE_U32:
|
||||
v = * (uint32_t *) mnl_attr_get_payload(nla[i]);
|
||||
fprintf(stderr, "\t%s: %u\n",
|
||||
cmdattr2name[i].name, ntohl(v));
|
||||
break;
|
||||
case MNL_TYPE_NUL_STRING:
|
||||
fprintf(stderr, "\t%s: %s\n",
|
||||
cmdattr2name[i].name,
|
||||
(const char *) mnl_attr_get_payload(nla[i]));
|
||||
break;
|
||||
case MNL_TYPE_NESTED:
|
||||
if (i == IPSET_ATTR_DATA) {
|
||||
switch (cmd) {
|
||||
case IPSET_CMD_ADD:
|
||||
case IPSET_CMD_DEL:
|
||||
case IPSET_CMD_TEST:
|
||||
if (mnl_attr_parse_nested(nla[i], adt_attr_cb, adt) < 0) {
|
||||
fprintf(stderr, "\tADT: cannot validate and parse attributes\n");
|
||||
continue;
|
||||
}
|
||||
debug_cadt_attrs(IPSET_ATTR_ADT_MAX,
|
||||
adt_attrs,
|
||||
adtattr2name,
|
||||
adt);
|
||||
break;
|
||||
default:
|
||||
if (mnl_attr_parse_nested(nla[i], create_attr_cb, cattr) < 0) {
|
||||
fprintf(stderr, "\tCREATE: cannot validate and parse attributes\n");
|
||||
continue;
|
||||
}
|
||||
debug_cadt_attrs(IPSET_ATTR_CREATE_MAX,
|
||||
create_attrs,
|
||||
createattr2name,
|
||||
cattr);
|
||||
}
|
||||
} else {
|
||||
struct nlattr *tb;
|
||||
mnl_attr_for_each_nested(tb, nla[i]) {
|
||||
memset(adt, 0, sizeof(adt));
|
||||
if (mnl_attr_parse_nested(tb, adt_attr_cb, adt) < 0) {
|
||||
fprintf(stderr, "\tADT: cannot validate and parse attributes\n");
|
||||
continue;
|
||||
}
|
||||
debug_cadt_attrs(IPSET_ATTR_ADT_MAX,
|
||||
adt_attrs,
|
||||
adtattr2name,
|
||||
adt);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "\t%s: unresolved!\n",
|
||||
cmdattr2name[i].name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ipset_debug_msg(const char *dir, void *buffer, int len)
|
||||
{
|
||||
const struct nlmsghdr *nlh = buffer;
|
||||
struct nlattr *nla[IPSET_ATTR_CMD_MAX+1] = {};
|
||||
int cmd, nfmsglen = MNL_ALIGN(sizeof(struct nfgenmsg));
|
||||
|
||||
debug = 0;
|
||||
while (mnl_nlmsg_ok(nlh, len)) {
|
||||
switch (nlh->nlmsg_type) {
|
||||
case NLMSG_NOOP:
|
||||
case NLMSG_DONE:
|
||||
case NLMSG_OVERRUN:
|
||||
fprintf(stderr, "Message header: %s msg %s\n"
|
||||
"\tlen %d\n"
|
||||
"\tseq %u\n",
|
||||
dir,
|
||||
nlh->nlmsg_type == NLMSG_NOOP ? "NOOP" :
|
||||
nlh->nlmsg_type == NLMSG_DONE ? "DONE" : "OVERRUN",
|
||||
len, nlh->nlmsg_seq);
|
||||
goto next_msg;
|
||||
case NLMSG_ERROR: {
|
||||
const struct nlmsgerr *err = mnl_nlmsg_get_payload(nlh);
|
||||
fprintf(stderr, "Message header: %s msg ERROR\n"
|
||||
"\tlen %d\n"
|
||||
"\terrcode %d\n"
|
||||
"\tseq %u\n",
|
||||
dir, len, err->error, nlh->nlmsg_seq);
|
||||
goto next_msg;
|
||||
}
|
||||
default:
|
||||
;
|
||||
}
|
||||
cmd = ipset_get_nlmsg_type(nlh);
|
||||
fprintf(stderr, "Message header: %s cmd %s (%d)\n"
|
||||
"\tlen %d\n"
|
||||
"\tflag %s\n"
|
||||
"\tseq %u\n",
|
||||
dir,
|
||||
cmd <= IPSET_CMD_NONE ? "NONE!" :
|
||||
cmd >= IPSET_CMD_MAX ? "MAX!" : cmd2name[cmd], cmd,
|
||||
len,
|
||||
!(nlh->nlmsg_flags & NLM_F_EXCL) ? "EXIST" : "none",
|
||||
nlh->nlmsg_seq);
|
||||
if (cmd <= IPSET_CMD_NONE || cmd >= IPSET_CMD_MAX)
|
||||
goto next_msg;
|
||||
memset(nla, 0, sizeof(nla));
|
||||
if (mnl_attr_parse(nlh, nfmsglen, cmd_attr_cb, nla) < MNL_CB_STOP) {
|
||||
fprintf(stderr, "\tcannot validate and parse attributes\n");
|
||||
goto next_msg;
|
||||
}
|
||||
debug_cmd_attrs(cmd, nla);
|
||||
next_msg:
|
||||
nlh = mnl_nlmsg_next(nlh, &len);
|
||||
}
|
||||
debug = 1;
|
||||
}
|
@@ -83,7 +83,6 @@ ipset_mnl_fill_hdr(struct ipset_handle *handle, enum ipset_cmd cmd,
|
||||
nlh->nlmsg_flags = NLM_F_REQUEST;
|
||||
if (cmdflags[cmd-1] & NLM_F_ACK)
|
||||
nlh->nlmsg_flags |= NLM_F_ACK;
|
||||
nlh->nlmsg_seq = ++handle->seq;
|
||||
|
||||
ghdr = mnl_nlmsg_put_extra_header(nlh, sizeof(struct genlmsghdr));
|
||||
ghdr->cmd = cmd;
|
||||
@@ -102,19 +101,24 @@ ipset_mnl_query(struct ipset_handle *handle, void *buffer, size_t len)
|
||||
assert(handle);
|
||||
assert(buffer);
|
||||
|
||||
nlh->nlmsg_seq = ++handle->seq;
|
||||
#ifdef IPSET_DEBUG
|
||||
ipset_debug_msg("sent", nlh, nlh->nlmsg_len);
|
||||
#endif
|
||||
if (mnl_socket_sendto(handle->h, nlh, nlh->nlmsg_len) < 0)
|
||||
return -ECOMM;
|
||||
|
||||
D("message sent");
|
||||
ret = mnl_socket_recvfrom(handle->h, buffer, len);
|
||||
D("message received, ret: %d", ret);
|
||||
#ifdef IPSET_DEBUG
|
||||
ipset_debug_msg("received", buffer, ret);
|
||||
#endif
|
||||
while (ret > 0) {
|
||||
ret = mnl_cb_run2(buffer, ret,
|
||||
handle->seq, handle->portid,
|
||||
handle->cb_ctl[NLMSG_MIN_TYPE],
|
||||
handle->data,
|
||||
handle->cb_ctl, NLMSG_MIN_TYPE);
|
||||
D("nfln_cb_run2, ret: %d", ret);
|
||||
D("nfln_cb_run2, ret: %d, errno %d", ret, errno);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
ret = mnl_socket_recvfrom(handle->h, buffer, len);
|
||||
|
@@ -667,8 +667,15 @@ parse_ipaddr(struct ipset_session *session,
|
||||
char *saved = strdup(str);
|
||||
char *a, *tmp = saved;
|
||||
struct addrinfo *info;
|
||||
enum ipset_opt copt = opt == IPSET_OPT_IP ? IPSET_OPT_CIDR
|
||||
: IPSET_OPT_CIDR2;
|
||||
enum ipset_opt copt, opt2;
|
||||
|
||||
if (opt == IPSET_OPT_IP) {
|
||||
copt = IPSET_OPT_CIDR;
|
||||
opt2 = IPSET_OPT_IP_TO;
|
||||
} else {
|
||||
copt = IPSET_OPT_CIDR2;
|
||||
opt2 = IPSET_OPT_IP2_TO;
|
||||
}
|
||||
|
||||
if (tmp == NULL)
|
||||
return ipset_err(session,
|
||||
@@ -691,7 +698,7 @@ parse_ipaddr(struct ipset_session *session,
|
||||
|| !range)
|
||||
goto out;
|
||||
freeaddrinfo(info);
|
||||
aerr = get_addrinfo(session, IPSET_OPT_IP_TO, a, &info, family);
|
||||
aerr = get_addrinfo(session, opt2, a, &info, family);
|
||||
|
||||
out:
|
||||
if (aerr != EINVAL)
|
||||
@@ -973,6 +980,46 @@ ipset_parse_ip4_single6(struct ipset_session *session,
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_parse_ip4_net6 - parse IPv4|IPv6 address or address/cidr pattern
|
||||
* @session: session structure
|
||||
* @opt: option kind of the data
|
||||
* @str: string to parse
|
||||
*
|
||||
* Parse string as an IPv4|IPv6 address or address/cidr pattern. For IPv4,
|
||||
* address range is valid too.
|
||||
* If family is not set yet in the data blob, INET is assumed.
|
||||
* The values are stored in the data blob of the session.
|
||||
*
|
||||
* FIXME: if the hostname resolves to multiple addresses,
|
||||
* the first one is used only.
|
||||
*
|
||||
* Returns 0 on success or a negative error code.
|
||||
*/
|
||||
int
|
||||
ipset_parse_ip4_net6(struct ipset_session *session,
|
||||
enum ipset_opt opt, const char *str)
|
||||
{
|
||||
struct ipset_data *data;
|
||||
uint8_t family;
|
||||
|
||||
assert(session);
|
||||
assert(opt == IPSET_OPT_IP || opt == IPSET_OPT_IP2);
|
||||
assert(str);
|
||||
|
||||
data = ipset_session_data(session);
|
||||
family = ipset_data_family(data);
|
||||
|
||||
if (family == AF_UNSPEC) {
|
||||
family = AF_INET;
|
||||
ipset_data_set(data, IPSET_OPT_FAMILY, &family);
|
||||
}
|
||||
|
||||
return family == AF_INET ? parse_ip(session, opt, str, IPADDR_ANY)
|
||||
: ipset_parse_ipnet(session, opt, str);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* ipset_parse_iptimeout - parse IPv4|IPv6 address and timeout
|
||||
* @session: session structure
|
||||
|
@@ -37,6 +37,7 @@ struct ipset_session {
|
||||
/* Command state */
|
||||
enum ipset_cmd cmd; /* Current command */
|
||||
uint32_t lineno; /* Current lineno in restore mode */
|
||||
uint32_t printed_set; /* Printed sets so far */
|
||||
char saved_setname[IPSET_MAXNAMELEN]; /* Saved setname */
|
||||
const struct ipset_type *saved_type; /* Saved type */
|
||||
struct nlattr *nested[IPSET_NEST_MAX]; /* Pointer to nest levels */
|
||||
@@ -138,6 +139,8 @@ ipset_envopt_parse(struct ipset_session *session, int opt,
|
||||
case IPSET_ENV_QUIET:
|
||||
case IPSET_ENV_RESOLVE:
|
||||
case IPSET_ENV_EXIST:
|
||||
case IPSET_ENV_LIST_SETNAME:
|
||||
case IPSET_ENV_LIST_HEADER:
|
||||
session->envopts |= opt;
|
||||
return 0;
|
||||
default:
|
||||
@@ -468,6 +471,10 @@ static const struct ipset_attr_policy adt_attrs[] = {
|
||||
.type = MNL_TYPE_U8,
|
||||
.opt = IPSET_OPT_CIDR2,
|
||||
},
|
||||
[IPSET_ATTR_IP2_TO] = {
|
||||
.type = MNL_TYPE_NESTED,
|
||||
.opt = IPSET_OPT_IP2_TO,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct ipset_attr_policy ipaddr_attrs[] = {
|
||||
@@ -480,6 +487,10 @@ static const struct ipset_attr_policy ipaddr_attrs[] = {
|
||||
},
|
||||
};
|
||||
|
||||
#ifdef IPSET_DEBUG
|
||||
static int debug = 1;
|
||||
#endif
|
||||
|
||||
static int
|
||||
generic_data_attr_cb(const struct nlattr *attr, void *data,
|
||||
int attr_max, const struct ipset_attr_policy *policy)
|
||||
@@ -487,14 +498,14 @@ generic_data_attr_cb(const struct nlattr *attr, void *data,
|
||||
const struct nlattr **tb = data;
|
||||
int type = mnl_attr_get_type(attr);
|
||||
|
||||
D("attr type: %u, len %u", type, attr->nla_len);
|
||||
IF_D(debug, "attr type: %u, len %u", type, attr->nla_len);
|
||||
if (mnl_attr_type_valid(attr, attr_max) < 0) {
|
||||
D("attr type: %u INVALID", type);
|
||||
IF_D(debug, "attr type: %u INVALID", type);
|
||||
return MNL_CB_ERROR;
|
||||
}
|
||||
if (mnl_attr_validate(attr, policy[type].type) < 0) {
|
||||
D("attr type: %u POLICY, attrlen %u", type,
|
||||
mnl_attr_get_payload_len(attr));
|
||||
IF_D(debug, "attr type: %u POLICY, attrlen %u", type,
|
||||
mnl_attr_get_payload_len(attr));
|
||||
return MNL_CB_ERROR;
|
||||
}
|
||||
if (policy[type].type == MNL_TYPE_NUL_STRING
|
||||
@@ -829,8 +840,9 @@ list_create(struct ipset_session *session, struct nlattr *nla[])
|
||||
type->name);
|
||||
break;
|
||||
case IPSET_LIST_PLAIN:
|
||||
safe_snprintf(session, "Name: %s\n"
|
||||
safe_snprintf(session, "%sName: %s\n"
|
||||
"Type: %s\nHeader: ",
|
||||
session->printed_set ? "\n" : "",
|
||||
ipset_data_setname(data),
|
||||
type->name);
|
||||
break;
|
||||
@@ -887,18 +899,24 @@ list_create(struct ipset_session *session, struct nlattr *nla[])
|
||||
safe_dprintf(session, ipset_print_number, IPSET_OPT_MEMSIZE);
|
||||
safe_snprintf(session, "\nReferences: ");
|
||||
safe_dprintf(session, ipset_print_number, IPSET_OPT_REFERENCES);
|
||||
safe_snprintf(session, "\nMembers:\n");
|
||||
safe_snprintf(session,
|
||||
session->envopts & IPSET_ENV_LIST_HEADER ?
|
||||
"\n" : "\nMembers:\n");
|
||||
break;
|
||||
case IPSET_LIST_XML:
|
||||
safe_snprintf(session, "</elements>\n <memsize>");
|
||||
safe_snprintf(session, " <memsize>");
|
||||
safe_dprintf(session, ipset_print_number, IPSET_OPT_MEMSIZE);
|
||||
safe_snprintf(session, "</memsize>\n <references>");
|
||||
safe_dprintf(session, ipset_print_number, IPSET_OPT_REFERENCES);
|
||||
safe_snprintf(session, "</references>\n </header>\n <members>\n");
|
||||
safe_snprintf(session,
|
||||
session->envopts & IPSET_ENV_LIST_HEADER ?
|
||||
"</references>\n </header>\n" :
|
||||
"</references>\n </header>\n <members>\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
session->printed_set++;
|
||||
|
||||
return MNL_CB_OK;
|
||||
}
|
||||
@@ -910,16 +928,17 @@ print_set_done(struct ipset_session *session)
|
||||
? "NONE" : session->saved_setname);
|
||||
switch (session->mode) {
|
||||
case IPSET_LIST_XML:
|
||||
if (session->saved_setname[0] == '\0')
|
||||
safe_snprintf(session, "\n");
|
||||
else
|
||||
if (session->envopts & IPSET_ENV_LIST_SETNAME)
|
||||
break;
|
||||
if (session->envopts & IPSET_ENV_LIST_HEADER) {
|
||||
if (session->saved_setname[0] != '\0')
|
||||
safe_snprintf(session, "</ipset>\n");
|
||||
break;
|
||||
}
|
||||
if (session->saved_setname[0] != '\0')
|
||||
safe_snprintf(session, " </members>\n</ipset>\n");
|
||||
break;
|
||||
case IPSET_LIST_SAVE:
|
||||
/* No empty lines between the sets */
|
||||
break;
|
||||
default:
|
||||
safe_snprintf(session, "\n");
|
||||
break;
|
||||
}
|
||||
return call_outfn(session) ? MNL_CB_ERROR : MNL_CB_STOP;
|
||||
@@ -931,8 +950,11 @@ callback_list(struct ipset_session *session, struct nlattr *nla[],
|
||||
{
|
||||
struct ipset_data *data = session->data;
|
||||
|
||||
if (setjmp(printf_failure))
|
||||
if (setjmp(printf_failure)) {
|
||||
session->saved_setname[0] = '\0';
|
||||
session->printed_set = 0;
|
||||
return MNL_CB_ERROR;
|
||||
}
|
||||
|
||||
if (!nla[IPSET_ATTR_SETNAME])
|
||||
FAILURE("Broken %s kernel message: missing setname!",
|
||||
@@ -940,6 +962,17 @@ callback_list(struct ipset_session *session, struct nlattr *nla[],
|
||||
|
||||
ATTR2DATA(session, nla, IPSET_ATTR_SETNAME, cmd_attrs);
|
||||
D("setname %s", ipset_data_setname(data));
|
||||
if (session->envopts & IPSET_ENV_LIST_SETNAME &&
|
||||
session->mode != IPSET_LIST_SAVE) {
|
||||
if (session->mode == IPSET_LIST_XML)
|
||||
safe_snprintf(session, "<ipset name=\"%s\"/>\n",
|
||||
ipset_data_setname(data));
|
||||
else
|
||||
safe_snprintf(session, "%s\n",
|
||||
ipset_data_setname(data));
|
||||
return call_outfn(session) ? MNL_CB_ERROR : MNL_CB_OK;
|
||||
}
|
||||
|
||||
if (STREQ(ipset_data_setname(data), session->saved_setname)) {
|
||||
/* Header part already seen */
|
||||
if (ipset_data_test(data, IPSET_OPT_TYPE)
|
||||
@@ -1422,6 +1455,9 @@ rawdata2attr(struct ipset_session *session, struct nlmsghdr *nlh,
|
||||
return 1;
|
||||
|
||||
switch (attr->type) {
|
||||
case MNL_TYPE_NUL_STRING:
|
||||
alen = strlen((const char *)d) + 1;
|
||||
break;
|
||||
case MNL_TYPE_U32: {
|
||||
uint32_t value = htonl(*(const uint32_t *)d);
|
||||
|
||||
@@ -1497,7 +1533,7 @@ addattr_adt(struct ipset_session *session,
|
||||
static int
|
||||
build_send_private_msg(struct ipset_session *session, enum ipset_cmd cmd)
|
||||
{
|
||||
char buffer[PRIVATE_MSG_BUFLEN] __attribute__ ((aligned));
|
||||
char buffer[PRIVATE_MSG_BUFLEN] __attribute__ ((aligned)) = {};
|
||||
struct nlmsghdr *nlh = (void *)buffer;
|
||||
struct ipset_data *data = session->data;
|
||||
int len = PRIVATE_MSG_BUFLEN, ret;
|
||||
@@ -1592,7 +1628,12 @@ build_msg(struct ipset_session *session, bool aggregate)
|
||||
IPSET_ATTR_REVISION, cmd_attrs);
|
||||
D("family: %u, type family %u",
|
||||
ipset_data_family(data), type->family);
|
||||
ADDATTR(session, nlh, data, IPSET_ATTR_FAMILY, AF_INET, cmd_attrs);
|
||||
if (ipset_data_test(data, IPSET_OPT_FAMILY))
|
||||
ADDATTR(session, nlh, data, IPSET_ATTR_FAMILY,
|
||||
AF_INET, cmd_attrs);
|
||||
else
|
||||
/* bitmap:port and list:set types */
|
||||
mnl_attr_put_u8(nlh, IPSET_ATTR_FAMILY, AF_UNSPEC);
|
||||
|
||||
/* Type-specific create attributes */
|
||||
D("call open_nested");
|
||||
@@ -1604,11 +1645,26 @@ build_msg(struct ipset_session *session, bool aggregate)
|
||||
}
|
||||
case IPSET_CMD_DESTROY:
|
||||
case IPSET_CMD_FLUSH:
|
||||
case IPSET_CMD_LIST:
|
||||
case IPSET_CMD_SAVE:
|
||||
if (ipset_data_test(data, IPSET_SETNAME))
|
||||
ADDATTR_SETNAME(session, nlh, data);
|
||||
break;
|
||||
case IPSET_CMD_LIST: {
|
||||
uint32_t flags = 0;
|
||||
|
||||
if (session->envopts & IPSET_ENV_LIST_SETNAME)
|
||||
flags |= IPSET_FLAG_LIST_SETNAME;
|
||||
if (session->envopts & IPSET_ENV_LIST_HEADER)
|
||||
flags |= IPSET_FLAG_LIST_HEADER;
|
||||
if (ipset_data_test(data, IPSET_SETNAME))
|
||||
ADDATTR_SETNAME(session, nlh, data);
|
||||
if (flags && session->mode != IPSET_LIST_SAVE) {
|
||||
ipset_data_set(data, IPSET_OPT_FLAGS, &flags);
|
||||
ADDATTR(session, nlh, data, IPSET_ATTR_FLAGS, AF_INET,
|
||||
cmd_attrs);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IPSET_CMD_RENAME:
|
||||
case IPSET_CMD_SWAP:
|
||||
if (!ipset_data_test(data, IPSET_SETNAME))
|
||||
@@ -1729,6 +1785,7 @@ ipset_commit(struct ipset_session *session)
|
||||
|
||||
/* Reset saved data and nested state */
|
||||
session->saved_setname[0] = '\0';
|
||||
session->printed_set = 0;
|
||||
for (i = session->nestid - 1; i >= 0; i--)
|
||||
session->nested[i] = NULL;
|
||||
session->nestid = 0;
|
||||
@@ -1926,3 +1983,7 @@ ipset_session_fini(struct ipset_session *session)
|
||||
free(session);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef IPSET_DEBUG
|
||||
#include "debug.c"
|
||||
#endif
|
||||
|
@@ -267,6 +267,19 @@ create_type_get(struct ipset_session *session)
|
||||
kmax, tmin);
|
||||
}
|
||||
|
||||
/* Disable unsupported revisions */
|
||||
for (match = NULL, t = typelist; t != NULL; t = t->next) {
|
||||
/* Skip revisions which are unsupported by the kernel */
|
||||
if (t->kernel_check == IPSET_KERNEL_MISMATCH)
|
||||
continue;
|
||||
if (ipset_match_typename(typename, t)
|
||||
&& MATCH_FAMILY(t, family)) {
|
||||
if (t->revision < kmin || t->revision > kmax)
|
||||
t->kernel_check = IPSET_KERNEL_MISMATCH;
|
||||
else if (match == NULL)
|
||||
match = t;
|
||||
}
|
||||
}
|
||||
match->kernel_check = IPSET_KERNEL_OK;
|
||||
found:
|
||||
ipset_data_set(data, IPSET_OPT_TYPE, match);
|
||||
|
Reference in New Issue
Block a user