summaryrefslogtreecommitdiffstats
path: root/src/libct.c
diff options
context:
space:
mode:
author/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=pablo/emailAddress=pablo@netfilter.org </C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=pablo/emailAddress=pablo@netfilter.org>2005-10-16 21:13:29 +0000
committer/C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=pablo/emailAddress=pablo@netfilter.org </C=DE/ST=Berlin/L=Berlin/O=Netfilter Project/OU=Development/CN=pablo/emailAddress=pablo@netfilter.org>2005-10-16 21:13:29 +0000
commitda9b980f8d34c436b31d5a0a09b4ea27849c9c82 (patch)
tree8b3e27bae375b64c2b3d35e1e9b1bb226f9514a1 /src/libct.c
parentcce8dd1bd45465dd9b18e4f02b5d007cb39079b0 (diff)
See ChangeLog
Diffstat (limited to 'src/libct.c')
-rw-r--r--src/libct.c660
1 files changed, 0 insertions, 660 deletions
diff --git a/src/libct.c b/src/libct.c
deleted file mode 100644
index 36aacbd..0000000
--- a/src/libct.c
+++ /dev/null
@@ -1,660 +0,0 @@
-/*
- * (C) 2005 by Pablo Neira Ayuso <pablo@eurodev.net>
- * Harald Welte <laforge@netfilter.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-#include <stdio.h>
-#include <getopt.h>
-#include <dlfcn.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <errno.h>
-#include <string.h>
-/* From kernel.h */
-#define INT_MAX ((int)(~0U>>1))
-#define INT_MIN (-INT_MAX - 1)
-#include <libnfnetlink_conntrack/libnfnetlink_conntrack.h>
-#include "linux_list.h"
-#include "libct_proto.h"
-
-#if 0
-#define DEBUGP printf
-#else
-#define DEBUGP
-#endif
-
-static struct ctnl_handle cth;
-extern char *lib_dir;
-extern struct list_head proto_list;
-extern char *proto2str[];
-
-static void dump_tuple(struct ctnl_tuple *tp)
-{
- fprintf(stdout, "tuple %p: %u %u.%u.%u.%u:%hu -> %u.%u.%u.%u:%hu\n",
- tp, tp->protonum,
- NIPQUAD(tp->src.v4), ntohs(tp->l4src.all),
- NIPQUAD(tp->dst.v4), ntohs(tp->l4dst.all));
-}
-
-static void print_status(unsigned int status)
-{
- if (status & IPS_ASSURED)
- fprintf(stdout, "[ASSURED] ");
- if (!(status & IPS_SEEN_REPLY))
- fprintf(stdout, "[UNREPLIED] ");
-}
-
-static void parse_ip(struct nfattr *attr, struct ctnl_tuple *tuple)
-{
- struct nfattr *tb[CTA_IP_MAX];
-
- memset(tb, 0, CTA_IP_MAX * sizeof(struct nfattr *));
-
- nfnl_parse_nested(tb, CTA_IP_MAX, attr);
- if (tb[CTA_IP_V4_SRC-1])
- tuple->src.v4 = *(u_int32_t *)NFA_DATA(tb[CTA_IP_V4_SRC-1]);
-
- if (tb[CTA_IP_V4_DST-1])
- tuple->dst.v4 = *(u_int32_t *)NFA_DATA(tb[CTA_IP_V4_DST-1]);
-}
-
-static void parse_proto(struct nfattr *attr, struct ctnl_tuple *tuple)
-{
- struct nfattr *tb[CTA_PROTO_MAX];
- struct ctproto_handler *h;
- int dir = CTNL_DIR_REPLY;
-
- memset(tb, 0, CTA_PROTO_MAX * sizeof(struct nfattr *));
-
- nfnl_parse_nested(tb, CTA_PROTO_MAX, attr);
- if (tb[CTA_PROTO_NUM-1])
- tuple->protonum = *(u_int8_t *)NFA_DATA(tb[CTA_PROTO_NUM-1]);
-
- h = findproto(proto2str[tuple->protonum]);
- if (h && h->parse_proto)
- h->parse_proto(tb, tuple);
-}
-
-static void parse_tuple(struct nfattr *attr, struct ctnl_tuple *tuple)
-{
- struct nfattr *tb[CTA_TUPLE_MAX];
-
- memset(tb, 0, CTA_TUPLE_MAX*sizeof(struct nfattr *));
-
- nfnl_parse_nested(tb, CTA_TUPLE_MAX, attr);
- if (tb[CTA_TUPLE_IP-1])
- parse_ip(tb[CTA_TUPLE_IP-1], tuple);
- if (tb[CTA_TUPLE_PROTO-1])
- parse_proto(tb[CTA_TUPLE_PROTO-1], tuple);
-}
-
-static void parse_protoinfo(struct nfattr *attr, struct ctnl_conntrack *ct)
-{
- struct nfattr *tb[CTA_PROTOINFO_MAX];
- struct ctproto_handler *h;
-
- memset(tb, 0, CTA_PROTOINFO_MAX*sizeof(struct nfattr *));
-
- nfnl_parse_nested(tb,CTA_PROTOINFO_MAX, attr);
-
- h = findproto(proto2str[ct->tuple[CTNL_DIR_ORIGINAL].protonum]);
- if (h && h->parse_protoinfo)
- h->parse_protoinfo(tb, ct);
-}
-
-/* Pablo: What is the equivalence of be64_to_cpu in userspace?
- *
- * Harald: Good question. I don't think there's a standard way [yet?],
- * so I'd suggest manually implementing it by "#if little endian" bitshift
- * operations in C (at least for now).
- *
- * All the payload of any nfattr will always be in network byte order.
- * This would allow easy transport over a real network in the future
- * (e.g. jamal's netlink2).
- *
- * Pablo: I've called it __be64_to_cpu instead of be64_to_cpu, since maybe
- * there will one in the userspace headers someday. We don't want to
- * pollute POSIX space naming,
- */
-
-#include <byteswap.h>
-#if __BYTE_ORDER == __BIG_ENDIAN
-# define __be64_to_cpu(x) (x)
-# else
-# if __BYTE_ORDER == __LITTLE_ENDIAN
-# define __be64_to_cpu(x) __bswap_64(x)
-# endif
-#endif
-
-static void parse_counters(struct nfattr *attr, struct ctnl_conntrack *ct,
- enum ctattr_type parent)
-{
- struct nfattr *tb[CTA_COUNTERS_MAX];
- int dir = (parent == CTA_COUNTERS_ORIG ? CTNL_DIR_REPLY
- : CTNL_DIR_ORIGINAL);
-
- memset(tb, 0, CTA_COUNTERS_MAX*sizeof(struct nfattr *));
-
- nfnl_parse_nested(tb, CTA_COUNTERS_MAX, attr);
- if (tb[CTA_COUNTERS_PACKETS-1])
- ct->counters[dir].packets
- = __be64_to_cpu(*(u_int64_t *)
- NFA_DATA(tb[CTA_COUNTERS_PACKETS-1]));
- if (tb[CTA_COUNTERS_BYTES-1])
- ct->counters[dir].bytes
- = __be64_to_cpu(*(u_int64_t *)
- NFA_DATA(tb[CTA_COUNTERS_BYTES-1]));
-}
-
-/* Some people seem to like counting in decimal... */
-#define STATUS 1
-#define PROTOINFO 2
-#define TIMEOUT 4
-#define MARK 8
-#define COUNTERS 16
-#define USE 32
-#define ID 64
-
-static int handler(struct sockaddr_nl *sock, struct nlmsghdr *nlh, void *arg)
-{
- struct nfgenmsg *nfmsg;
- struct nfattr *nfa;
- int min_len = sizeof(struct nfgenmsg);;
- struct ctproto_handler *h = NULL;
- struct nfattr *attr = NFM_NFA(NLMSG_DATA(nlh));
- int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len);
- struct ctnl_conntrack ct;
- unsigned int flags = 0;
-
- memset(&ct, 0, sizeof(struct ctnl_conntrack));
-
- nfmsg = NLMSG_DATA(nlh);
-
- if (nlh->nlmsg_len < min_len)
- return -EINVAL;
-
- while (NFA_OK(attr, attrlen)) {
- switch(attr->nfa_type) {
- case CTA_TUPLE_ORIG:
- parse_tuple(attr, &ct.tuple[CTNL_DIR_ORIGINAL]);
- break;
- case CTA_TUPLE_REPLY:
- parse_tuple(attr, &ct.tuple[CTNL_DIR_REPLY]);
- break;
- case CTA_STATUS:
- ct.status = ntohl(*(u_int32_t *)NFA_DATA(attr));
- flags |= STATUS;
- break;
- case CTA_PROTOINFO:
- parse_protoinfo(attr, &ct);
- flags |= PROTOINFO;
- break;
- case CTA_TIMEOUT:
- ct.timeout = ntohl(*(u_int32_t *)NFA_DATA(attr));
- flags |= TIMEOUT;
- break;
- case CTA_MARK:
- ct.mark = ntohl(*(u_int32_t *)NFA_DATA(attr));
- flags |= MARK;
- break;
- case CTA_COUNTERS_ORIG:
- case CTA_COUNTERS_REPLY:
- parse_counters(attr, &ct, attr->nfa_type-1);
- flags |= COUNTERS;
- break;
- case CTA_USE:
- ct.use = ntohl(*(u_int32_t *)NFA_DATA(attr));
- flags |= USE;
- break;
- case CTA_ID:
- ct.id = ntohl(*(u_int32_t *)NFA_DATA(attr));
- flags |= ID;
- break;
- }
- attr = NFA_NEXT(attr, attrlen);
- }
-
- fprintf(stdout, "%-8s %u ",
- proto2str[ct.tuple[CTNL_DIR_ORIGINAL].protonum] == NULL ?
- "unknown" : proto2str[ct.tuple[CTNL_DIR_ORIGINAL].protonum],
- ct.tuple[CTNL_DIR_ORIGINAL].protonum);
-
- if (flags & TIMEOUT)
- fprintf(stdout, "%lu ", ct.timeout);
-
- h = findproto(proto2str[ct.tuple[CTNL_DIR_ORIGINAL].protonum]);
- if ((flags & PROTOINFO) && h && h->print_protoinfo)
- h->print_protoinfo(&ct.protoinfo);
-
- fprintf(stdout, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ",
- NIPQUAD(ct.tuple[CTNL_DIR_ORIGINAL].src.v4),
- NIPQUAD(ct.tuple[CTNL_DIR_ORIGINAL].dst.v4));
-
- if (h && h->print_proto)
- h->print_proto(&ct.tuple[CTNL_DIR_ORIGINAL]);
-
- if (flags & COUNTERS)
- fprintf(stdout, "packets=%llu bytes=%llu ",
- ct.counters[CTNL_DIR_ORIGINAL].packets,
- ct.counters[CTNL_DIR_ORIGINAL].bytes);
-
- fprintf(stdout, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ",
- NIPQUAD(ct.tuple[CTNL_DIR_REPLY].src.v4),
- NIPQUAD(ct.tuple[CTNL_DIR_REPLY].dst.v4));
-
- h = findproto(proto2str[ct.tuple[CTNL_DIR_ORIGINAL].protonum]);
- if (h && h->print_proto)
- h->print_proto(&ct.tuple[CTNL_DIR_REPLY]);
-
- if (flags & COUNTERS)
- fprintf(stdout, "packets=%llu bytes=%llu ",
- ct.counters[CTNL_DIR_REPLY].packets,
- ct.counters[CTNL_DIR_REPLY].bytes);
-
- if (flags & STATUS)
- print_status(ct.status);
-
- if (flags & MARK)
- fprintf(stdout, "mark=%lu ", ct.mark);
- if (flags & USE)
- fprintf(stdout, "use=%u ", ct.use);
- if (flags & ID)
- fprintf(stdout, "id=%u ", ct.id);
-
- fprintf(stdout, "\n");
-
- return 0;
-}
-
-static char *typemsg2str(type, flags)
-{
- char *ret = "[UNKNOWN]";
-
- if (type == IPCTNL_MSG_CT_NEW) {
- if (flags & NLM_F_CREATE)
- ret = "[NEW]";
- else
- ret = "[UPDATE]";
- } else if (type == IPCTNL_MSG_CT_DELETE)
- ret = "[DESTROY]";
-
- return ret;
-}
-
-static int event_handler(struct sockaddr_nl *sock, struct nlmsghdr *nlh,
- void *arg)
-{
- int type = NFNL_MSG_TYPE(nlh->nlmsg_type);
- fprintf(stdout, "%9s ", typemsg2str(type, nlh->nlmsg_flags));
- return handler(sock, nlh, arg);
-}
-
-static int expect_handler(struct sockaddr_nl *sock, struct nlmsghdr *nlh, void *arg)
-{
- struct nfgenmsg *nfmsg;
- struct nfattr *nfa;
- int min_len = sizeof(struct nfgenmsg);;
- struct ctproto_handler *h = NULL;
- struct nfattr *attr = NFM_NFA(NLMSG_DATA(nlh));
- int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len);
- struct ctnl_tuple tuple, mask;
- unsigned long timeout = 0;
- u_int32_t id = 0;
- unsigned int flags;
-
- memset(&tuple, 0, sizeof(struct ctnl_tuple));
- memset(&mask, 0, sizeof(struct ctnl_tuple));
-
- nfmsg = NLMSG_DATA(nlh);
-
- if (nlh->nlmsg_len < min_len)
- return -EINVAL;
-
- while (NFA_OK(attr, attrlen)) {
- switch(attr->nfa_type) {
-
- case CTA_EXPECT_TUPLE:
- parse_tuple(attr, &tuple);
- break;
- case CTA_EXPECT_MASK:
- parse_tuple(attr, &mask);
- break;
- case CTA_EXPECT_TIMEOUT:
- timeout = htonl(*(unsigned long *)
- NFA_DATA(attr));
- break;
- case CTA_EXPECT_ID:
- id = htonl(*(u_int32_t *)NFA_DATA(attr));
- break;
- }
- attr = NFA_NEXT(attr, attrlen);
- }
- fprintf(stdout, "%ld proto=%d ", timeout, tuple.protonum);
-
- fprintf(stdout, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ",
- NIPQUAD(tuple.src.v4),
- NIPQUAD(tuple.dst.v4));
-
- fprintf(stdout, "src=%u.%u.%u.%u dst=%u.%u.%u.%u ",
- NIPQUAD(mask.src.v4),
- NIPQUAD(mask.dst.v4));
-
- fprintf(stdout, "id=%u ", id);
-
- fputc('\n', stdout);
-
- return 0;
-}
-
-int create_conntrack(struct ctnl_tuple *orig,
- struct ctnl_tuple *reply,
- unsigned long timeout,
- union ctnl_protoinfo *proto,
- unsigned int status,
- struct ctnl_nat *range)
-{
- struct ctnl_conntrack ct;
- int ret;
-
- memset(&ct, 0, sizeof(struct ctnl_conntrack));
- ct.tuple[CTNL_DIR_ORIGINAL] = *orig;
- ct.tuple[CTNL_DIR_REPLY] = *reply;
- ct.timeout = htonl(timeout);
- ct.status = status;
- ct.protoinfo = *proto;
- if (range)
- ct.nat = *range;
-
- if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, 0)) < 0)
- return ret;
-
- ret = ctnl_new_conntrack(&cth, &ct);
-
- ctnl_close(&cth);
-
- return ret;
-}
-
-int update_conntrack(struct ctnl_tuple *orig,
- struct ctnl_tuple *reply,
- unsigned long timeout,
- union ctnl_protoinfo *proto,
- unsigned int status)
-{
- struct ctnl_conntrack ct;
- int ret;
-
- memset(&ct, 0, sizeof(struct ctnl_conntrack));
- ct.tuple[CTNL_DIR_ORIGINAL] = *orig;
- ct.tuple[CTNL_DIR_REPLY] = *reply;
- ct.timeout = htonl(timeout);
- ct.status = status;
- ct.protoinfo = *proto;
-
- if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, 0)) < 0)
- return ret;
-
- ret = ctnl_upd_conntrack(&cth, &ct);
-
- ctnl_close(&cth);
-
- return ret;
-}
-
-int delete_conntrack(struct ctnl_tuple *tuple, int dir)
-{
- int ret;
-
- if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, 0)) < 0)
- return ret;
-
- ret = ctnl_del_conntrack(&cth, tuple, dir);
- ctnl_close(&cth);
-
- return ret;
-}
-
-/* get_conntrack_handler */
-int get_conntrack(struct ctnl_tuple *tuple, int dir)
-{
- struct ctnl_msg_handler h = {
- .type = 0,
- .handler = handler
- };
- int ret;
-
- if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, 0)) < 0)
- return ret;
-
- ctnl_register_handler(&cth, &h);
-
- ret = ctnl_get_conntrack(&cth, tuple, dir);
- ctnl_close(&cth);
-
- return ret;
-}
-
-int dump_conntrack_table(int zero)
-{
- int ret;
- struct ctnl_msg_handler h = {
- .type = IPCTNL_MSG_CT_NEW, /* Hm... really? */
- .handler = handler
- };
-
- if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, 0)) < 0)
- return ret;
-
- ctnl_register_handler(&cth, &h);
-
- if (zero) {
- ret = ctnl_list_conntrack_zero_counters(&cth, AF_INET);
- } else
- ret = ctnl_list_conntrack(&cth, AF_INET);
-
- ctnl_close(&cth);
-
- return ret;
-}
-
-static void event_sighandler(int s)
-{
- fprintf(stdout, "Now closing conntrack event dumping...\n");
- ctnl_close(&cth);
- exit(0);
-}
-
-int event_conntrack(unsigned int event_mask)
-{
- struct ctnl_msg_handler hnew = {
- .type = IPCTNL_MSG_CT_NEW,
- .handler = event_handler
- };
- struct ctnl_msg_handler hdestroy = {
- .type = IPCTNL_MSG_CT_DELETE,
- .handler = event_handler
- };
- int ret;
-
- if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, event_mask)) < 0)
- return ret;
-
- signal(SIGINT, event_sighandler);
- ctnl_register_handler(&cth, &hnew);
- ctnl_register_handler(&cth, &hdestroy);
- ret = ctnl_event_conntrack(&cth, AF_INET);
- ctnl_close(&cth);
-
- return 0;
-}
-
-struct ctproto_handler *findproto(char *name)
-{
- void *h = NULL;
- struct list_head *i;
- struct ctproto_handler *cur = NULL, *handler = NULL;
-
- if (!name)
- return handler;
-
- lib_dir = getenv("CONNTRACK_LIB_DIR");
- if (!lib_dir)
- lib_dir = CONNTRACK_LIB_DIR;
-
- list_for_each(i, &proto_list) {
- cur = (struct ctproto_handler *) i;
- if (strcmp(cur->name, name) == 0) {
- handler = cur;
- break;
- }
- }
-
- if (!handler) {
- char path[sizeof("libct_proto_.so")
- + strlen(name) + strlen(lib_dir)];
- sprintf(path, "%s/libct_proto_%s.so", lib_dir, name);
- if (dlopen(path, RTLD_NOW))
- handler = findproto(name);
- else
- DEBUGP(stderr, "%s\n", dlerror());
- }
-
- return handler;
-}
-
-void register_proto(struct ctproto_handler *h)
-{
- if (strcmp(h->version, LIBCT_VERSION) != 0) {
- fprintf(stderr, "plugin `%s': version %s (I'm %s)\n",
- h->name, h->version, LIBCT_VERSION);
- exit(1);
- }
- list_add(&h->head, &proto_list);
-}
-
-void unregister_proto(struct ctproto_handler *h)
-{
- list_del(&h->head);
-}
-
-int dump_expect_list()
-{
- struct ctnl_msg_handler h = {
- .type = IPCTNL_MSG_EXP_NEW,
- .handler = expect_handler
- };
- int ret;
-
- if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK_EXP, 0)) < 0)
- return ret;
-
- ctnl_register_handler(&cth, &h);
-
- ret = ctnl_list_expect(&cth, AF_INET);
- ctnl_close(&cth);
-
- return ret;
-}
-
-int flush_conntrack()
-{
- int ret;
-
- if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK, 0)) < 0)
- return ret;
-
- ret = ctnl_flush_conntrack(&cth);
- ctnl_close(&cth);
-
- return ret;
-}
-
-int get_expect(struct ctnl_tuple *tuple)
-{
- struct ctnl_msg_handler h = {
- .type = IPCTNL_MSG_EXP_NEW,
- .handler = expect_handler
- };
- int ret;
-
- if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK_EXP, 0)) < 0)
- return 0;
-
- ctnl_register_handler(&cth, &h);
-
- ret = ctnl_get_expect(&cth, tuple);
- ctnl_close(&cth);
-
- return ret;
-}
-
-int create_expectation(struct ctnl_tuple *tuple,
- struct ctnl_tuple *exptuple,
- struct ctnl_tuple *mask,
- unsigned long timeout)
-{
- int ret;
-
- if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK_EXP, 0)) < 0)
- return ret;
-
-
- ret = ctnl_new_expect(&cth, tuple, exptuple, mask, timeout);
- ctnl_close(&cth);
-
- return ret;
-}
-
-int delete_expectation(struct ctnl_tuple *tuple)
-{
- int ret;
-
- if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK_EXP, 0)) < 0)
- return ret;
-
- ret = ctnl_del_expect(&cth, tuple);
- ctnl_close(&cth);
-
- return ret;
-}
-
-int event_expectation(unsigned int event_mask)
-{
- struct ctnl_msg_handler hnew = {
- .type = IPCTNL_MSG_EXP_NEW,
- .handler = expect_handler
- };
- struct ctnl_msg_handler hdestroy = {
- .type = IPCTNL_MSG_EXP_DELETE,
- .handler = expect_handler
- };
- int ret;
-
- if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK_EXP, event_mask)) < 0)
- return ret;
-
- ctnl_register_handler(&cth, &hnew);
- ctnl_register_handler(&cth, &hdestroy);
- ret = ctnl_event_expect(&cth, AF_INET);
- ctnl_close(&cth);
-
- return ret;
-}
-
-int flush_expectation()
-{
- int ret;
-
- if ((ret = ctnl_open(&cth, NFNL_SUBSYS_CTNETLINK_EXP, 0)) < 0)
- return ret;
-
- ret = ctnl_flush_expect(&cth);
- ctnl_close(&cth);
-
- return ret;
-}
-