]> granicus.if.org Git - ipset/commitdiff
Protocol-level debugging support added
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Tue, 24 May 2011 07:33:38 +0000 (09:33 +0200)
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Tue, 24 May 2011 07:33:38 +0000 (09:33 +0200)
include/libipset/session.h
lib/debug.c [new file with mode: 0644]
lib/mnl.c
lib/session.c

index 5ccdd6c6cba09a81fb0ca62284c258e2b24be872..9301ccd5aa770bbac690311ef6bfced8b6de729e 100644 (file)
@@ -96,4 +96,6 @@ typedef int (*ipset_outfn)(const char *fmt, ...)
 extern struct ipset_session * ipset_session_init(ipset_outfn outfn);
 extern int ipset_session_fini(struct ipset_session *session);
 
+extern void ipset_debug_msg(const char *dir, void *buffer, int len);
+
 #endif /* LIBIPSET_SESSION_H */
diff --git a/lib/debug.c b/lib/debug.c
new file mode 100644 (file)
index 0000000..174567d
--- /dev/null
@@ -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;
+}
index 75cadb6d474b448bf721dbb034d3b28224f68e1f..d18ec044504dc3f2d713ea287c4da83f566e3cb2 100644 (file)
--- a/lib/mnl.c
+++ b/lib/mnl.c
@@ -92,12 +92,16 @@ ipset_mnl_query(struct ipset_handle *handle, void *buffer, size_t len)
        assert(handle);
        assert(buffer);
 
+#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,
index a9c7c33274b97059ebbd9e18fc323dcafe3f9958..bab1846f93bb1788ba1fb2f9930c26402c5d709b 100644 (file)
@@ -485,6 +485,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)
@@ -492,14 +496,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
@@ -1969,3 +1973,7 @@ ipset_session_fini(struct ipset_session *session)
        free(session);
        return 0;
 }
+
+#ifdef IPSET_DEBUG
+#include "debug.c"
+#endif