mirror of
git://git.code.sf.net/p/xtables-addons/xtables-addons
synced 2025-09-07 05:05:12 +02:00
269 lines
7.9 KiB
C
269 lines
7.9 KiB
C
/* 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;
|
|
}
|