From b4c3a23c884c24f4e5d941fb928cf49561a9cdf9 Mon Sep 17 00:00:00 2001 From: "/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=pablo/emailAddress=pablo@netfilter.org" Date: Tue, 19 Dec 2006 17:41:53 +0000 Subject: Introduce the new libnetfilter_conntrack API, features: - object oriented infrastructure - extensible and configurable output (XML) - low level functions to interact with netlink details - fairly documented Still backward compatible. --- src/conntrack/snprintf_xml.c | 413 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 413 insertions(+) create mode 100644 src/conntrack/snprintf_xml.c (limited to 'src/conntrack/snprintf_xml.c') diff --git a/src/conntrack/snprintf_xml.c b/src/conntrack/snprintf_xml.c new file mode 100644 index 0000000..1cc62d8 --- /dev/null +++ b/src/conntrack/snprintf_xml.c @@ -0,0 +1,413 @@ +/* + * (C) 2006 by Pablo Neira Ayuso + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + */ + +#include "internal.h" + +/* + * XML output sample: + * + * + * + * + * 192.168.0.1 + * 192.168.0.2 + * + * + * 80 + * 56665 + * + * + * 10 + * 1 + * + * + * + * + * 192.168.0.2 + * 192.168.0.1 + * + * + * 80 + * 56665 + * + * + * 5029 + * 12 + * + * + * + * + * ESTABLISHED + * + * 100 + * 1 + * 1 + * + * + * + */ + +static char *proto2str[IPPROTO_MAX] = { + [IPPROTO_TCP] = "tcp", + [IPPROTO_UDP] = "udp", + [IPPROTO_ICMP] = "icmp", + [IPPROTO_SCTP] = "sctp" +}; +static char *l3proto2str[AF_MAX] = { + [AF_INET] = "ipv4", + [AF_INET6] = "ipv6" +}; + +enum { + __ADDR_SRC = 0, + __ADDR_DST, +}; + +static void buffer_size(int ret, unsigned int *size, unsigned int *len) +{ + *size += ret; + *len -= ret; +} + +static char *__proto2str(u_int8_t protonum) +{ + return proto2str[protonum] ? proto2str[protonum] : "unknown"; +} + +static char *__l3proto2str(u_int8_t protonum) +{ + return l3proto2str[protonum] ? l3proto2str[protonum] : "unknown"; +} + +static int __snprintf_ipv4_xml(char *buf, + unsigned int len, + const struct __nfct_tuple *tuple, + unsigned int type) +{ + struct in_addr addr = { + .s_addr = (type == __ADDR_SRC) ? tuple->src.v4 : tuple->dst.v4, + }; + + return snprintf(buf, len, "%s", inet_ntoa(addr)); +} + +static int __snprintf_ipv6_xml(char *buf, + unsigned int len, + const struct __nfct_tuple *tuple, + unsigned int type) +{ + struct in6_addr addr; + static char tmp[INET6_ADDRSTRLEN]; + const void *p = (type == __ADDR_SRC) ? &tuple->src.v6 : &tuple->dst.v6; + + memcpy(&addr.in6_u, p, sizeof(struct in6_addr)); + + if (!inet_ntop(AF_INET6, &addr, tmp, sizeof(tmp))) + return -1; + + return snprintf(buf, len, "%s", tmp); +} + +static int __snprintf_addr_xml(char *buf, + unsigned int len, + const struct __nfct_tuple *tuple, + unsigned int type) +{ + int ret; + unsigned int size = 0; + + switch(type) { + case __ADDR_SRC: + ret = snprintf(buf, len, ""); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + break; + case __ADDR_DST: + ret = snprintf(buf+size, len, ""); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + break; + } + + switch (tuple->l3protonum) { + case AF_INET: + ret = __snprintf_ipv4_xml(buf+size, len, tuple, type); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + break; + case AF_INET6: + ret = __snprintf_ipv6_xml(buf+size, len, tuple, type); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + break; + } + + switch(type) { + case __ADDR_SRC: + ret = snprintf(buf+size, len, ""); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + break; + case __ADDR_DST: + ret = snprintf(buf+size, len, ""); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + break; + } + + return size; +} + +static int __snprintf_proto_xml(char *buf, + unsigned int len, + const struct __nfct_tuple *tuple, + unsigned int type) +{ + int ret = 0; + unsigned int size = 0; + + switch(tuple->protonum) { + case IPPROTO_TCP: + case IPPROTO_UDP: + case IPPROTO_SCTP: + if (type == __ADDR_SRC) { + ret = snprintf(buf, len, "%u", + tuple->l4src.tcp.port); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + } else { + ret = snprintf(buf, len, "%u", + tuple->l4dst.tcp.port); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + } + break; + } + + return ret; +} + +static int __snprintf_counters_xml(char *buf, + unsigned int len, + const struct nf_conntrack *ct, + unsigned int type) +{ + int ret; + unsigned int size = 0; + + ret = snprintf(buf, len, "%llu", + ct->counters[type].packets); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + + ret = snprintf(buf+size, len, "%llu", + ct->counters[type].bytes); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + + return size; +} + +static int __snprintf_tuple_xml(char *buf, + unsigned int len, + const struct nf_conntrack *ct, + unsigned int dir) +{ + int ret; + unsigned int size = 0; + const struct __nfct_tuple *tuple = &ct->tuple[dir]; + + ret = snprintf(buf, len, "", + dir == __DIR_ORIG ? "original" : "reply"); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + + ret = snprintf(buf+size, len, + "", + tuple->l3protonum, __l3proto2str(tuple->l3protonum)); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + + ret = __snprintf_addr_xml(buf+size, len, tuple, __DIR_ORIG); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + + ret = __snprintf_addr_xml(buf+size, len, tuple, __DIR_REPL); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + + ret = snprintf(buf+size, len, ""); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + + ret = snprintf(buf+size, len, + "", + tuple->protonum, __proto2str(tuple->protonum)); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + + ret = __snprintf_proto_xml(buf+size, len, tuple, __DIR_ORIG); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + + ret = __snprintf_proto_xml(buf+size, len, tuple, __DIR_REPL); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + + ret = snprintf(buf+size, len, ""); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + + if (test_bit(ATTR_ORIG_COUNTER_PACKETS, ct->set) && + test_bit(ATTR_ORIG_COUNTER_BYTES, ct->set)) { + ret = snprintf(buf+size, len, ""); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + + ret = __snprintf_counters_xml(buf+size, len, ct, dir); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + + ret = snprintf(buf+size, len, ""); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + } + + ret = snprintf(buf+size, len, ""); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + + return size; +} + +int __snprintf_conntrack_xml(char *buf, + unsigned int len, + const struct nf_conntrack *ct, + const unsigned int msg_type, + const unsigned int flags) +{ + int ret = 0; + unsigned int size = 0; + + switch(msg_type) { + case NFCT_T_NEW: + ret = snprintf(buf, len, ""); + break; + case NFCT_T_UPDATE: + ret = snprintf(buf, len, ""); + break; + } + + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + + ret = __snprintf_tuple_xml(buf+size, len, ct, __DIR_ORIG); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + + ret = __snprintf_tuple_xml(buf+size, len, ct, __DIR_REPL); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + + if (test_bit(ATTR_TIMEOUT, ct->set) || + test_bit(ATTR_MARK, ct->set) || + test_bit(ATTR_USE, ct->set) || + test_bit(ATTR_STATUS, ct->set)) { + ret = snprintf(buf+size, len, + ""); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + } + + if (test_bit(ATTR_TIMEOUT, ct->set)) { + ret = snprintf(buf+size, len, + "%u", ct->timeout); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + } + + if (test_bit(ATTR_MARK, ct->set)) { + ret = snprintf(buf+size, len, "%u", ct->mark); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + } + + if (test_bit(ATTR_USE, ct->set)) { + ret = snprintf(buf+size, len, "%u", ct->use); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + } + + if (test_bit(ATTR_STATUS, ct->set) + && ct->status & IPS_ASSURED) { + ret = snprintf(buf+size, len, ""); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + } + + if (test_bit(ATTR_STATUS, ct->set) + && !(ct->status & IPS_SEEN_REPLY)) { + ret = snprintf(buf+size, len, ""); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + } + + if (test_bit(ATTR_TIMEOUT, ct->set) || + test_bit(ATTR_MARK, ct->set) || + test_bit(ATTR_USE, ct->set) || + test_bit(ATTR_STATUS, ct->set)) { + ret = snprintf(buf+size, len, ""); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + } + + ret = snprintf(buf+size, len, ""); + if (ret == -1) + return -1; + buffer_size(ret, &size, &len); + + return size; +} -- cgit v1.2.3