All of lore.kernel.org
 help / color / mirror / Atom feed
From: Philip Craig <philipc@snapgear.com>
To: Netfilter Developer Mailing List <netfilter-devel@lists.netfilter.org>
Subject: [PATCH 3/3] libnl: add netfilter log support
Date: Mon, 03 Sep 2007 15:12:32 +1000	[thread overview]
Message-ID: <46DB97C0.3060602@snapgear.com> (raw)
In-Reply-To: <46DB9716.1020400@snapgear.com>

[-- Attachment #1: Type: text/plain, Size: 1 bytes --]



[-- Attachment #2: nfnl_log.patch --]
[-- Type: text/x-diff, Size: 29757 bytes --]

---
 include/linux/netfilter/nfnetlink_log.h |   96 +++++++
 include/netlink-types.h                 |   22 +
 include/netlink/netfilter/log.h         |  105 +++++++
 lib/netfilter/log.c                     |  349 ++++++++++++++++++++++++++
 lib/netfilter/log_obj.c                 |  425 ++++++++++++++++++++++++++++++++
 src/nf-log.c                            |  142 ++++++++++
 6 files changed, 1139 insertions(+)

Index: libnl/include/netlink-types.h
===================================================================
--- libnl.orig/include/netlink-types.h	2007-09-03 14:32:20.000000000 +1000
+++ libnl/include/netlink-types.h	2007-09-03 14:32:21.000000000 +1000
@@ -839,4 +839,26 @@ struct nfnl_ct {
 	struct nfnl_ct_dir	ct_repl;
 };
 
+struct nfnl_log {
+	NLHDR_COMMON
+
+	uint8_t			log_family;
+	uint8_t			log_hook;
+	uint16_t		log_hwproto;
+	uint32_t		log_mark;
+	struct timeval		log_timestamp;
+	uint32_t		log_indev;
+	uint32_t		log_outdev;
+	uint32_t		log_physindev;
+	uint32_t		log_physoutdev;
+	uint8_t			log_hwaddr[8];
+	int			log_hwaddr_len;
+	void *			log_payload;
+	int			log_payload_len;
+	char *			log_prefix;
+	uint32_t		log_uid;
+	uint32_t		log_seq;
+	uint32_t		log_seq_global;
+};
+
 #endif
Index: libnl/include/netlink/netfilter/log.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ libnl/include/netlink/netfilter/log.h	2007-09-03 14:32:21.000000000 +1000
@@ -0,0 +1,105 @@
+/*
+ * netlink/netfilter/log.h	Netfilter Log
+ *
+ *	This library is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU Lesser General Public
+ *	License as published by the Free Software Foundation version 2.1
+ *	of the License.
+ *
+ * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2007 Philip Craig <philipc@snapgear.com>
+ * Copyright (c) 2007 Secure Computing Corporation
+ */
+
+#ifndef NETLINK_LOG_H_
+#define NETLINK_LOG_H_
+
+#include <netlink/netlink.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct nl_handle;
+struct nlmsghdr;
+struct nfnl_log;
+
+extern struct nl_object_ops log_obj_ops;
+
+/* General */
+extern struct nfnl_log *nfnl_log_alloc(void);
+extern struct nfnl_log *nfnlmsg_log_parse(struct nlmsghdr *);
+
+extern void		nfnl_log_get(struct nfnl_log *);
+extern void		nfnl_log_put(struct nfnl_log *);
+
+extern struct nl_msg *	nfnl_log_build_bind(uint16_t);;
+extern int		nfnl_log_bind(struct nl_handle *, uint16_t);
+extern struct nl_msg *	nfnl_log_build_unbind(uint16_t);
+extern int		nfnl_log_unbind(struct nl_handle *, uint16_t);
+extern struct nl_msg *	nfnl_log_build_pf_bind(uint8_t);
+extern int		nfnl_log_pf_bind(struct nl_handle *, uint8_t);
+extern struct nl_msg *	nfnl_log_build_pf_unbind(uint8_t);
+extern int		nfnl_log_pf_unbind(struct nl_handle *, uint8_t);
+extern struct nl_msg *	nfnl_log_build_mode(uint16_t, uint8_t, uint32_t);
+extern int		nfnl_log_set_mode(struct nl_handle *, uint16_t,
+					  uint8_t, uint32_t);
+
+extern void		nfnl_log_set_family(struct nfnl_log *, uint8_t);
+extern uint8_t		nfnl_log_get_family(const struct nfnl_log *);
+
+extern void		nfnl_log_set_hwproto(struct nfnl_log *, uint16_t);
+extern int		nfnl_log_test_hwproto(const struct nfnl_log *);
+extern uint16_t		nfnl_log_get_hwproto(const struct nfnl_log *);
+
+extern void		nfnl_log_set_hook(struct nfnl_log *, uint8_t);
+extern int		nfnl_log_test_hook(const struct nfnl_log *);
+extern uint8_t		nfnl_log_get_hook(const struct nfnl_log *);
+
+extern void		nfnl_log_set_mark(struct nfnl_log *, uint32_t);
+extern int		nfnl_log_test_mark(const struct nfnl_log *);
+extern uint32_t		nfnl_log_get_mark(const struct nfnl_log *);
+
+extern void		nfnl_log_set_timestamp(struct nfnl_log *,
+					       struct timeval *);
+extern const struct timeval *nfnl_log_get_timestamp(const struct nfnl_log *);
+
+extern void		nfnl_log_set_indev(struct nfnl_log *, uint32_t);
+extern uint32_t		nfnl_log_get_indev(const struct nfnl_log *);
+
+extern void		nfnl_log_set_outdev(struct nfnl_log *, uint32_t);
+extern uint32_t		nfnl_log_get_outdev(const struct nfnl_log *);
+
+extern void		nfnl_log_set_physindev(struct nfnl_log *, uint32_t);
+extern uint32_t		nfnl_log_get_physindev(const struct nfnl_log *);
+
+extern void		nfnl_log_set_physoutdev(struct nfnl_log *, uint32_t);
+extern uint32_t		nfnl_log_get_physoutdev(const struct nfnl_log *);
+
+extern void		nfnl_log_set_hwaddr(struct nfnl_log *, uint8_t *, int);
+extern const uint8_t *	nfnl_log_get_hwaddr(const struct nfnl_log *, int *);
+
+extern int		nfnl_log_set_payload(struct nfnl_log *, uint8_t *, int);
+extern const void *	nfnl_log_get_payload(const struct nfnl_log *, int *);
+
+extern int		nfnl_log_set_prefix(struct nfnl_log *, void *);
+extern const char *	nfnl_log_get_prefix(const struct nfnl_log *);
+
+extern void		nfnl_log_set_uid(struct nfnl_log *, uint32_t);
+extern int		nfnl_log_test_uid(const struct nfnl_log *);
+extern uint32_t		nfnl_log_get_uid(const struct nfnl_log *);
+
+extern void		nfnl_log_set_seq(struct nfnl_log *, uint32_t);
+extern int		nfnl_log_test_seq(const struct nfnl_log *);
+extern uint32_t		nfnl_log_get_seq(const struct nfnl_log *);
+
+extern void		nfnl_log_set_seq_global(struct nfnl_log *, uint32_t);
+extern int		nfnl_log_test_seq_global(const struct nfnl_log *);
+extern uint32_t		nfnl_log_get_seq_global(const struct nfnl_log *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
Index: libnl/lib/netfilter/log.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ libnl/lib/netfilter/log.c	2007-09-03 14:32:21.000000000 +1000
@@ -0,0 +1,349 @@
+/*
+ * lib/netfilter/log.c	Netfilter Log
+ *
+ *	This library is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU Lesser General Public
+ *	License as published by the Free Software Foundation version 2.1
+ *	of the License.
+ *
+ * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2007 Philip Craig <philipc@snapgear.com>
+ * Copyright (c) 2007 Secure Computing Corporation
+ */
+
+/**
+ * @ingroup nfnl
+ * @defgroup log Log
+ * @brief
+ * @{
+ */
+
+#include <sys/types.h>
+#include <linux/netfilter/nfnetlink_log.h>
+
+#include <netlink-local.h>
+#include <netlink/attr.h>
+#include <netlink/netfilter/nfnl.h>
+#include <netlink/netfilter/log.h>
+
+static struct nl_cache_ops nfnl_log_ops;
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+static uint64_t ntohll(uint64_t x)
+{
+	return x;
+}
+#elif __BYTE_ORDER == __LITTLE_ENDIAN
+static uint64_t ntohll(uint64_t x)
+{
+	return __bswap_64(x);
+}
+#endif
+
+static struct nla_policy log_policy[NFULA_MAX+1] = {
+	[NFULA_PACKET_HDR]		= {
+		.minlen = sizeof(struct nfulnl_msg_packet_hdr)
+	},
+	[NFULA_MARK]			= { .type = NLA_U32 },
+	[NFULA_TIMESTAMP]		= {
+		.minlen = sizeof(struct nfulnl_msg_packet_timestamp)
+	},
+	[NFULA_IFINDEX_INDEV]		= { .type = NLA_U32 },
+	[NFULA_IFINDEX_OUTDEV]		= { .type = NLA_U32 },
+	[NFULA_IFINDEX_PHYSINDEV]	= { .type = NLA_U32 },
+	[NFULA_IFINDEX_PHYSOUTDEV]	= { .type = NLA_U32 },
+	[NFULA_HWADDR]			= {
+		.minlen = sizeof(struct nfulnl_msg_packet_hw)
+	},
+	//[NFULA_PAYLOAD]
+	[NFULA_PREFIX]			= { .type = NLA_STRING, },
+	[NFULA_UID]			= { .type = NLA_U32 },
+	[NFULA_SEQ]			= { .type = NLA_U32 },
+	[NFULA_SEQ_GLOBAL]		= { .type = NLA_U32 },
+};
+
+struct nfnl_log *nfnlmsg_log_parse(struct nlmsghdr *nlh)
+{
+	struct nfnl_log *log;
+	struct nlattr *tb[NFULA_MAX+1];
+	struct nlattr *attr;
+	int err;
+
+	log = nfnl_log_alloc();
+	if (!log)
+		return NULL;
+
+	log->ce_msgtype = nlh->nlmsg_type;
+
+	err = nlmsg_parse(nlh, sizeof(struct nfgenmsg), tb, NFULA_MAX,
+			  log_policy);
+	if (err < 0)
+		goto errout;
+
+	nfnl_log_set_family(log, nfnlmsg_family(nlh));
+
+	attr = tb[NFULA_PACKET_HDR];
+	if (attr) {
+		struct nfulnl_msg_packet_hdr *hdr = nla_data(attr);
+
+		nfnl_log_set_hwproto(log, hdr->hw_protocol);
+		nfnl_log_set_hook(log, hdr->hook);
+	}
+
+	attr = tb[NFULA_MARK];
+	if (attr)
+		nfnl_log_set_mark(log, ntohl(nla_get_u32(attr)));
+
+	attr = tb[NFULA_TIMESTAMP];
+	if (attr) {
+		struct nfulnl_msg_packet_timestamp *timestamp = nla_data(attr);
+		struct timeval tv;
+
+		tv.tv_sec = ntohll(timestamp->sec);
+		tv.tv_usec = ntohll(timestamp->usec);
+		nfnl_log_set_timestamp(log, &tv);
+	}
+
+	attr = tb[NFULA_IFINDEX_INDEV];
+	if (attr)
+		nfnl_log_set_indev(log, ntohl(nla_get_u32(attr)));
+
+	attr = tb[NFULA_IFINDEX_OUTDEV];
+	if (attr)
+		nfnl_log_set_outdev(log, ntohl(nla_get_u32(attr)));
+
+	attr = tb[NFULA_IFINDEX_PHYSINDEV];
+	if (attr)
+		nfnl_log_set_physindev(log, ntohl(nla_get_u32(attr)));
+
+	attr = tb[NFULA_IFINDEX_PHYSOUTDEV];
+	if (attr)
+		nfnl_log_set_physoutdev(log, ntohl(nla_get_u32(attr)));
+
+	attr = tb[NFULA_HWADDR];
+	if (attr) {
+		struct nfulnl_msg_packet_hw *hw = nla_data(attr);
+
+		nfnl_log_set_hwaddr(log, hw->hw_addr, ntohs(hw->hw_addrlen));
+	}
+
+	attr = tb[NFULA_PAYLOAD];
+	if (attr) {
+		err = nfnl_log_set_payload(log, nla_data(attr), nla_len(attr));
+		if (err < 0)
+			goto errout;
+	}
+
+	attr = tb[NFULA_PREFIX];
+	if (attr) {
+		err = nfnl_log_set_prefix(log, nla_data(attr));
+		if (err < 0)
+			goto errout;
+	}
+
+	attr = tb[NFULA_UID];
+	if (attr)
+		nfnl_log_set_uid(log, ntohl(nla_get_u32(attr)));
+
+	attr = tb[NFULA_SEQ];
+	if (attr)
+		nfnl_log_set_seq(log, ntohl(nla_get_u32(attr)));
+
+	attr = tb[NFULA_SEQ_GLOBAL];
+	if (attr)
+		nfnl_log_set_seq_global(log, ntohl(nla_get_u32(attr)));
+
+	return log;
+
+errout:
+	nfnl_log_put(log);
+	return NULL;
+}
+
+static int log_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
+			 struct nlmsghdr *nlh, void *arg)
+{
+	struct nl_parser_param *pp = arg;
+	struct nfnl_log *log;
+	int err;
+
+	log = nfnlmsg_log_parse(nlh);
+	if (log == NULL)
+		goto errout_errno;
+
+	err = pp->pp_cb((struct nl_object *) log, pp);
+	if (err < 0)
+		goto errout;
+
+	return P_ACCEPT;
+
+errout_errno:
+	err = nl_get_errno();
+errout:
+	nfnl_log_put(log);
+	return err;
+}
+
+/**
+ * @name Log Commands
+ * @{
+ */
+
+static struct nl_msg *build_log_cmd_msg(uint8_t family, uint16_t queuenum,
+					uint8_t command)
+{
+	struct nl_msg *msg;
+	struct nfulnl_msg_config_cmd cmd;
+
+	msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_ULOG, NFULNL_MSG_CONFIG, 0,
+				   family, queuenum);
+	if (msg == NULL)
+		return NULL;
+
+	cmd.command = command;
+	if (nla_put(msg, NFULA_CFG_CMD, sizeof(cmd), &cmd) < 0)
+		goto nla_put_failure;
+
+	return msg;
+
+nla_put_failure:
+	nlmsg_free(msg);
+	return NULL;
+}
+
+static int send_log_msg(struct nl_handle *handle, struct nl_msg *msg)
+{
+	int err;
+
+	err = nl_send_auto_complete(handle, msg);
+	nlmsg_free(msg);
+	if (err < 0)
+		return err;
+
+	return nl_wait_for_ack(handle);
+}
+
+struct nl_msg *nfnl_log_build_bind(uint16_t queuenum)
+{
+	return build_log_cmd_msg(0, queuenum, NFULNL_CFG_CMD_BIND);
+}
+
+int nfnl_log_bind(struct nl_handle *nlh, uint16_t queuenum)
+{
+	struct nl_msg *msg;
+
+	msg = nfnl_log_build_bind(queuenum);
+	if (!msg)
+		return nl_get_errno();
+
+	return send_log_msg(nlh, msg);
+}
+
+struct nl_msg *nfnl_log_build_unbind(uint16_t queuenum)
+{
+	return build_log_cmd_msg(0, queuenum, NFULNL_CFG_CMD_UNBIND);
+}
+
+int nfnl_log_unbind(struct nl_handle *nlh, uint16_t queuenum)
+{
+	struct nl_msg *msg;
+
+	msg = nfnl_log_build_bind(queuenum);
+	if (!msg)
+		return nl_get_errno();
+
+	return send_log_msg(nlh, msg);
+}
+
+struct nl_msg *nfnl_log_build_pf_bind(uint8_t pf)
+{
+	return build_log_cmd_msg(pf, 0, NFULNL_CFG_CMD_PF_BIND);
+}
+
+int nfnl_log_pf_bind(struct nl_handle *nlh, uint8_t pf)
+{
+	struct nl_msg *msg;
+
+	msg = nfnl_log_build_pf_bind(pf);
+	if (!msg)
+		return nl_get_errno();
+
+	return send_log_msg(nlh, msg);
+}
+
+struct nl_msg *nfnl_log_build_pf_unbind(uint8_t pf)
+{
+	return build_log_cmd_msg(pf, 0, NFULNL_CFG_CMD_PF_UNBIND);
+}
+
+int nfnl_log_pf_unbind(struct nl_handle *nlh, uint8_t pf)
+{
+	struct nl_msg *msg;
+
+	msg = nfnl_log_build_pf_unbind(pf);
+	if (!msg)
+		return nl_get_errno();
+
+	return send_log_msg(nlh, msg);
+}
+
+struct nl_msg *nfnl_log_build_mode(uint16_t queuenum, uint8_t copy_mode,
+				   uint32_t copy_range)
+{
+	struct nl_msg *msg;
+	struct nfulnl_msg_config_mode mode;
+
+	msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_ULOG, NFULNL_MSG_CONFIG, 0,
+			0, queuenum);
+	if (msg == NULL)
+		return NULL;
+
+	mode.copy_mode = copy_mode;
+	mode.copy_range = htonl(copy_range);
+	if (nla_put(msg, NFULA_CFG_MODE, sizeof(mode), &mode) < 0)
+		goto nla_put_failure;
+
+	return msg;
+
+nla_put_failure:
+	nlmsg_free(msg);
+	return NULL;
+}
+
+int nfnl_log_set_mode(struct nl_handle *nlh, uint16_t queuenum,
+		      uint8_t copy_mode, uint32_t copy_range)
+{
+	struct nl_msg *msg;
+
+	msg = nfnl_log_build_mode(queuenum, copy_mode, copy_range);
+	if (!msg)
+		return nl_get_errno();
+	return send_log_msg(nlh, msg);
+}
+
+/** @} */
+
+#define NFNLMSG_LOG_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_ULOG, (type))
+static struct nl_cache_ops nfnl_log_ops = {
+	.co_name		= "netfilter/log",
+	.co_hdrsize		= NFNL_HDRLEN,
+	.co_msgtypes		= {
+		{ NFNLMSG_LOG_TYPE(NFULNL_MSG_PACKET), NL_ACT_NEW, "new" },
+		END_OF_MSGTYPES_LIST,
+	},
+	.co_protocol		= NETLINK_NETFILTER,
+	.co_msg_parser		= log_msg_parser,
+	.co_obj_ops		= &log_obj_ops,
+};
+
+static void __init log_init(void)
+{
+	nl_cache_mngt_register(&nfnl_log_ops);
+}
+
+static void __exit log_exit(void)
+{
+	nl_cache_mngt_unregister(&nfnl_log_ops);
+}
+
+/** @} */
Index: libnl/lib/netfilter/log_obj.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ libnl/lib/netfilter/log_obj.c	2007-09-03 14:32:21.000000000 +1000
@@ -0,0 +1,425 @@
+/*
+ * lib/netfilter/log_obj.c	Netfilter Log Object
+ *
+ *	This library is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU Lesser General Public
+ *	License as published by the Free Software Foundation version 2.1
+ *	of the License.
+ *
+ * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2007 Philip Craig <philipc@snapgear.com>
+ * Copyright (c) 2007 Secure Computing Corporation
+ */
+
+#include <netlink-local.h>
+#include <netlink/netfilter/nfnl.h>
+#include <netlink/netfilter/log.h>
+
+/** @cond SKIP */
+#define LOG_ATTR_FAMILY			(1UL << 0)
+#define LOG_ATTR_HWPROTO		(1UL << 1)
+#define LOG_ATTR_HOOK			(1UL << 2)
+#define LOG_ATTR_MARK			(1UL << 3)
+#define LOG_ATTR_TIMESTAMP		(1UL << 4)
+#define LOG_ATTR_INDEV			(1UL << 5)
+#define LOG_ATTR_OUTDEV			(1UL << 6)
+#define LOG_ATTR_PHYSINDEV		(1UL << 7)
+#define LOG_ATTR_PHYSOUTDEV		(1UL << 8)
+#define LOG_ATTR_HWADDR			(1UL << 9)
+#define LOG_ATTR_PAYLOAD		(1UL << 10)
+#define LOG_ATTR_PREFIX			(1UL << 11)
+#define LOG_ATTR_UID			(1UL << 12)
+#define LOG_ATTR_SEQ			(1UL << 13)
+#define LOG_ATTR_SEQ_GLOBAL		(1UL << 14)
+/** @endcond */
+
+static void log_free_data(struct nl_object *c)
+{
+	struct nfnl_log *log = (struct nfnl_log *) c;
+
+	if (log == NULL)
+		return;
+
+	free(log->log_payload);
+	free(log->log_prefix);
+}
+
+static int log_clone(struct nl_object *_dst, struct nl_object *_src)
+{
+	struct nfnl_log *dst = (struct nfnl_log *) _dst;
+	struct nfnl_log *src = (struct nfnl_log *) _src;
+	int err;
+
+	if (src->log_payload) {
+		err = nfnl_log_set_payload(dst, src->log_payload,
+					   src->log_payload_len);
+		if (err < 0)
+			goto errout;
+	}
+
+	if (src->log_prefix) {
+		err = nfnl_log_set_prefix(dst, src->log_prefix);
+		if (err < 0)
+			goto errout;
+	}
+
+	return 0;
+errout:
+	return err;
+}
+
+static int log_dump(struct nl_object *a, struct nl_dump_params *p)
+{
+	struct nfnl_log *log = (struct nfnl_log *) a;
+	struct nl_cache *link_cache;
+	char buf[64];
+
+	link_cache = nl_cache_mngt_require("route/link");
+
+	if (log->ce_mask & LOG_ATTR_PREFIX)
+		dp_dump(p, "%s", log->log_prefix);
+
+	if (log->ce_mask & LOG_ATTR_INDEV) {
+		if (link_cache)
+			dp_dump(p, "IN=%s ",
+				rtnl_link_i2name(link_cache, log->log_indev,
+						 buf, sizeof(buf)));
+		else
+			dp_dump(p, "IN=%d ", log->log_indev);
+	}
+
+	if (log->ce_mask & LOG_ATTR_PHYSINDEV) {
+		if (link_cache)
+			dp_dump(p, "PHYSIN=%s ",
+				rtnl_link_i2name(link_cache, log->log_physindev,
+						 buf, sizeof(buf)));
+		else
+			dp_dump(p, "IN=%d ", log->log_physindev);
+	}
+
+	if (log->ce_mask & LOG_ATTR_OUTDEV) {
+		if (link_cache)
+			dp_dump(p, "OUT=%s ",
+				rtnl_link_i2name(link_cache, log->log_outdev,
+						 buf, sizeof(buf)));
+		else
+			dp_dump(p, "OUT=%d ", log->log_outdev);
+	}
+
+	if (log->ce_mask & LOG_ATTR_PHYSOUTDEV) {
+		if (link_cache)
+			dp_dump(p, "PHYSOUT=%s ",
+				rtnl_link_i2name(link_cache,log->log_physoutdev,
+						 buf, sizeof(buf)));
+		else
+			dp_dump(p, "PHYSOUT=%d ", log->log_physoutdev);
+	}
+
+	if (log->ce_mask & LOG_ATTR_HWADDR) {
+		int i;
+
+		dp_dump(p, "MAC");
+		for (i = 0; i < log->log_hwaddr_len; i++)
+			dp_dump(p, "%c%02x", i?':':'=', log->log_hwaddr[i]);
+		dp_dump(p, " ");
+	}
+
+	/* FIXME: parse the payload to get iptables LOG compatible format */
+
+	if (log->ce_mask & LOG_ATTR_FAMILY)
+		dp_dump(p, "FAMILY=%s ",
+			nl_af2str(log->log_family, buf, sizeof(buf)));
+
+	if (log->ce_mask & LOG_ATTR_HWPROTO)
+		dp_dump(p, "HWPROTO=%s ",
+			nl_ether_proto2str(ntohs(log->log_hwproto),
+					   buf, sizeof(buf)));
+
+	if (log->ce_mask & LOG_ATTR_HOOK)
+		dp_dump(p, "HOOK=%d ", log->log_hook);
+
+	if (log->ce_mask & LOG_ATTR_MARK)
+		dp_dump(p, "MARK=%d ", log->log_mark);
+
+	if (log->ce_mask & LOG_ATTR_PAYLOAD)
+		dp_dump(p, "PAYLOADLEN=%d ", log->log_payload_len);
+
+	if (log->ce_mask & LOG_ATTR_SEQ)
+		dp_dump(p, "SEQ=%d ", log->log_seq);
+
+	if (log->ce_mask & LOG_ATTR_SEQ_GLOBAL)
+		dp_dump(p, "SEQGLOBAL=%d ", log->log_seq_global);
+
+	dp_dump(p, "\n");
+
+	return 1;
+}
+
+/**
+ * @name Allocation/Freeing
+ * @{
+ */
+
+struct nfnl_log *nfnl_log_alloc(void)
+{
+	return (struct nfnl_log *) nl_object_alloc(&log_obj_ops);
+}
+
+void nfnl_log_get(struct nfnl_log *log)
+{
+	nl_object_get((struct nl_object *) log);
+}
+
+void nfnl_log_put(struct nfnl_log *log)
+{
+	nl_object_put((struct nl_object *) log);
+}
+
+/** @} */
+
+/**
+ * @name Attributes
+ * @{
+ */
+
+void nfnl_log_set_family(struct nfnl_log *log, uint8_t family)
+{
+	log->log_family = family;
+	log->ce_mask |= LOG_ATTR_FAMILY;
+}
+
+uint8_t nfnl_log_get_family(const struct nfnl_log *log)
+{
+	if (log->ce_mask & LOG_ATTR_FAMILY)
+		return log->log_family;
+	else
+		return AF_UNSPEC;
+}
+
+void nfnl_log_set_hwproto(struct nfnl_log *log, uint16_t hwproto)
+{
+	log->log_hwproto = hwproto;
+	log->ce_mask |= LOG_ATTR_HWPROTO;
+}
+
+int nfnl_log_test_hwproto(const struct nfnl_log *log)
+{
+	return !!(log->ce_mask & LOG_ATTR_HWPROTO);
+}
+
+uint16_t nfnl_log_get_hwproto(const struct nfnl_log *log)
+{
+	return log->log_hwproto;
+}
+
+void nfnl_log_set_hook(struct nfnl_log *log, uint8_t hook)
+{
+	log->log_hook = hook;
+	log->ce_mask |= LOG_ATTR_HOOK;
+}
+
+int nfnl_log_test_hook(const struct nfnl_log *log)
+{
+	return !!(log->ce_mask & LOG_ATTR_HOOK);
+}
+
+uint8_t nfnl_log_get_hook(const struct nfnl_log *log)
+{
+	return log->log_hook;
+}
+
+void nfnl_log_set_mark(struct nfnl_log *log, uint32_t mark)
+{
+	log->log_mark = mark;
+	log->ce_mask |= LOG_ATTR_MARK;
+}
+
+int nfnl_log_test_mark(const struct nfnl_log *log)
+{
+	return !!(log->ce_mask & LOG_ATTR_MARK);
+}
+
+uint32_t nfnl_log_get_mark(const struct nfnl_log *log)
+{
+	return log->log_mark;
+}
+
+void nfnl_log_set_timestamp(struct nfnl_log *log, struct timeval *tv)
+{
+	log->log_timestamp.tv_sec = tv->tv_sec;
+	log->log_timestamp.tv_usec = tv->tv_usec;
+	log->ce_mask |= LOG_ATTR_TIMESTAMP;
+}
+
+const struct timeval *nfnl_log_get_timestamp(const struct nfnl_log *log)
+{
+	if (!(log->ce_mask & LOG_ATTR_TIMESTAMP))
+		return NULL;
+	return &log->log_timestamp;
+}
+
+void nfnl_log_set_indev(struct nfnl_log *log, uint32_t indev)
+{
+	log->log_indev = indev;
+	log->ce_mask |= LOG_ATTR_INDEV;
+}
+
+uint32_t nfnl_log_get_indev(const struct nfnl_log *log)
+{
+	return log->log_indev;
+}
+
+void nfnl_log_set_outdev(struct nfnl_log *log, uint32_t outdev)
+{
+	log->log_outdev = outdev;
+	log->ce_mask |= LOG_ATTR_OUTDEV;
+}
+
+uint32_t nfnl_log_get_outdev(const struct nfnl_log *log)
+{
+	return log->log_outdev;
+}
+
+void nfnl_log_set_physindev(struct nfnl_log *log, uint32_t physindev)
+{
+	log->log_physindev = physindev;
+	log->ce_mask |= LOG_ATTR_PHYSINDEV;
+}
+
+uint32_t nfnl_log_get_physindev(const struct nfnl_log *log)
+{
+	return log->log_physindev;
+}
+
+void nfnl_log_set_physoutdev(struct nfnl_log *log, uint32_t physoutdev)
+{
+	log->log_physoutdev = physoutdev;
+	log->ce_mask |= LOG_ATTR_PHYSOUTDEV;
+}
+
+uint32_t nfnl_log_get_physoutdev(const struct nfnl_log *log)
+{
+	return log->log_physoutdev;
+}
+
+void nfnl_log_set_hwaddr(struct nfnl_log *log, uint8_t *hwaddr, int len)
+{
+	if (len > sizeof(log->log_hwaddr))
+		len = sizeof(log->log_hwaddr);
+	log->log_hwaddr_len = len;
+	memcpy(log->log_hwaddr, hwaddr, len);
+	log->ce_mask |= LOG_ATTR_HWADDR;
+}
+
+const uint8_t *nfnl_log_get_hwaddr(const struct nfnl_log *log, int *len)
+{
+	if (!(log->ce_mask & LOG_ATTR_HWADDR)) {
+		*len = 0;
+		return NULL;
+	}
+
+	*len = log->log_hwaddr_len;
+	return log->log_hwaddr;
+}
+
+int nfnl_log_set_payload(struct nfnl_log *log, uint8_t *payload, int len)
+{
+	free(log->log_payload);
+	log->log_payload = malloc(len);
+	if (!log->log_payload)
+		return nl_errno(ENOMEM);
+
+	memcpy(log->log_payload, payload, len);
+	log->log_payload_len = len;
+	log->ce_mask |= LOG_ATTR_PAYLOAD;
+	return 0;
+}
+
+const void *nfnl_log_get_payload(const struct nfnl_log *log, int *len)
+{
+	if (!(log->ce_mask & LOG_ATTR_PAYLOAD)) {
+		*len = 0;
+		return NULL;
+	}
+
+	*len = log->log_payload_len;
+	return log->log_payload;
+}
+
+int nfnl_log_set_prefix(struct nfnl_log *log, void *prefix)
+{
+	free(log->log_prefix);
+	log->log_prefix = strdup(prefix);
+	if (!log->log_prefix)
+		return nl_errno(ENOMEM);
+
+	log->ce_mask |= LOG_ATTR_PREFIX;
+	return 0;
+}
+
+const char *nfnl_log_get_prefix(const struct nfnl_log *log)
+{
+	return log->log_prefix;
+}
+
+void nfnl_log_set_uid(struct nfnl_log *log, uint32_t uid)
+{
+	log->log_uid = uid;
+	log->ce_mask |= LOG_ATTR_UID;
+}
+
+int nfnl_log_test_uid(const struct nfnl_log *log)
+{
+	return !!(log->ce_mask & LOG_ATTR_UID);
+}
+
+uint32_t nfnl_log_get_uid(const struct nfnl_log *log)
+{
+	return log->log_uid;
+}
+
+void nfnl_log_set_seq(struct nfnl_log *log, uint32_t seq)
+{
+	log->log_seq = seq;
+	log->ce_mask |= LOG_ATTR_SEQ;
+}
+
+int nfnl_log_test_seq(const struct nfnl_log *log)
+{
+	return !!(log->ce_mask & LOG_ATTR_SEQ);
+}
+
+uint32_t nfnl_log_get_seq(const struct nfnl_log *log)
+{
+	return log->log_seq;
+}
+
+void nfnl_log_set_seq_global(struct nfnl_log *log, uint32_t seq_global)
+{
+	log->log_seq_global = seq_global;
+	log->ce_mask |= LOG_ATTR_SEQ_GLOBAL;
+}
+
+int nfnl_log_test_seq_global(const struct nfnl_log *log)
+{
+	return !!(log->ce_mask & LOG_ATTR_SEQ_GLOBAL);
+}
+
+uint32_t nfnl_log_get_seq_global(const struct nfnl_log *log)
+{
+	return log->log_seq_global;
+}
+
+/** @} */
+
+struct nl_object_ops log_obj_ops = {
+	.oo_name		= "netfilter/log",
+	.oo_size		= sizeof(struct nfnl_log),
+	.oo_free_data		= log_free_data,
+	.oo_clone		= log_clone,
+	.oo_dump[NL_DUMP_BRIEF]	= log_dump,
+	.oo_dump[NL_DUMP_FULL]	= log_dump,
+	.oo_dump[NL_DUMP_STATS]	= log_dump,
+};
+
+/** @} */
Index: libnl/src/nf-log.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ libnl/src/nf-log.c	2007-09-03 14:39:32.000000000 +1000
@@ -0,0 +1,142 @@
+/*
+ * src/nf-log.c     Monitor netfilter log events
+ *
+ *	This library is free software; you can redistribute it and/or
+ *	modify it under the terms of the GNU Lesser General Public
+ *	License as published by the Free Software Foundation version 2.1
+ *	of the License.
+ *
+ * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2007 Philip Craig <philipc@snapgear.com>
+ * Copyright (c) 2007 Secure Computing Corporation
+ */
+
+#include <sys/types.h>
+#include <linux/netfilter/nfnetlink_log.h>
+
+#include "utils.h"
+#include <netlink/netfilter/nfnl.h>
+#include <netlink/netfilter/log.h>
+
+static void obj_input(struct nl_object *obj, void *arg)
+{
+	struct nl_dump_params dp = {
+		.dp_type = NL_DUMP_STATS,
+		.dp_fd = stdout,
+		.dp_dump_msgtype = 1,
+	};
+
+	nl_object_dump(obj, &dp);
+}
+
+static int event_input(struct nl_msg *msg, void *arg)
+{
+	if (nl_msg_parse(msg, &obj_input, NULL) < 0)
+		fprintf(stderr, "<<EVENT>> Unknown message type\n");
+
+	/* Exit nl_recvmsgs_def() and return to the main select() */
+	return NL_EXIT;
+}
+
+int main(int argc, char *argv[])
+{
+	struct nl_handle *nfnlh;
+	struct nl_handle *rtnlh;
+        struct nl_cache *link_cache;
+	int err = 1;
+	int family, group;
+
+	if (nltool_init(argc, argv) < 0)
+		return -1;
+
+	nfnlh = nltool_alloc_handle();
+	if (nfnlh == NULL)
+		return -1;
+
+	nl_disable_sequence_check(nfnlh);
+
+	nl_socket_modify_cb(nfnlh, NL_CB_VALID, NL_CB_CUSTOM, event_input, NULL);
+
+	if ((argc > 1 && !strcasecmp(argv[1], "-h")) || argc < 3) {
+		printf("Usage: nf-log family group\n");
+		return 2;
+	}
+
+	if (nfnl_connect(nfnlh) < 0) {
+		fprintf(stderr, "%s\n", nl_geterror());
+		goto errout;
+	}
+
+	family = nl_str2af(argv[1]);
+	if (family == AF_UNSPEC) {
+		fprintf(stderr, "Unknown family: %s\n", argv[1]);
+		goto errout;
+	}
+	if (nfnl_log_pf_unbind(nfnlh, family) < 0) {
+		fprintf(stderr, "%s\n", nl_geterror());
+		goto errout;
+	}
+	if (nfnl_log_pf_bind(nfnlh, family) < 0) {
+		fprintf(stderr, "%s\n", nl_geterror());
+		goto errout;
+	}
+
+	group = nl_str2af(argv[2]);
+	if (nfnl_log_bind(nfnlh, group) < 0) {
+		fprintf(stderr, "%s\n", nl_geterror());
+		goto errout;
+	}
+
+	if (nfnl_log_set_mode(nfnlh, 0, NFULNL_COPY_PACKET, 0xffff) < 0) {
+		fprintf(stderr, "%s\n", nl_geterror());
+		goto errout;
+	}
+
+	rtnlh = nltool_alloc_handle();
+	if (rtnlh == NULL) {
+		goto errout_close;
+	}
+
+	if (nl_connect(rtnlh, NETLINK_ROUTE) < 0) {
+		fprintf(stderr, "%s\n", nl_geterror());
+		goto errout;
+	}
+
+	if ((link_cache = rtnl_link_alloc_cache(rtnlh)) == NULL) {
+		fprintf(stderr, "%s\n", nl_geterror());
+		goto errout_close;
+	}
+
+	nl_cache_mngt_provide(link_cache);
+
+	while (1) {
+		fd_set rfds;
+		int nffd, rtfd, maxfd, retval;
+
+		FD_ZERO(&rfds);
+
+		maxfd = nffd = nl_socket_get_fd(nfnlh);
+		FD_SET(nffd, &rfds);
+
+		rtfd = nl_socket_get_fd(rtnlh);
+		FD_SET(rtfd, &rfds);
+		if (maxfd < rtfd)
+			maxfd = rtfd;
+
+		/* wait for an incoming message on the netlink socket */
+		retval = select(maxfd+1, &rfds, NULL, NULL, NULL);
+
+		if (retval) {
+			if (FD_ISSET(nffd, &rfds))
+				nl_recvmsgs_def(nfnlh);
+			if (FD_ISSET(rtfd, &rfds))
+				nl_recvmsgs_def(rtnlh);
+		}
+	}
+
+	nl_close(rtnlh);
+errout_close:
+	nl_close(nfnlh);
+errout:
+	return err;
+}
Index: libnl/include/linux/netfilter/nfnetlink_log.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ libnl/include/linux/netfilter/nfnetlink_log.h	2007-09-03 14:32:21.000000000 +1000
@@ -0,0 +1,96 @@
+#ifndef _NFNETLINK_LOG_H
+#define _NFNETLINK_LOG_H
+
+/* This file describes the netlink messages (i.e. 'protocol packets'),
+ * and not any kind of function definitions.  It is shared between kernel and
+ * userspace.  Don't put kernel specific stuff in here */
+
+#ifndef aligned_be64
+#define aligned_be64 u_int64_t __attribute__((aligned(8)))
+#endif
+
+#include <linux/types.h>
+#include <linux/netfilter/nfnetlink.h>
+
+enum nfulnl_msg_types {
+	NFULNL_MSG_PACKET,		/* packet from kernel to userspace */
+	NFULNL_MSG_CONFIG,		/* connect to a particular queue */
+
+	NFULNL_MSG_MAX
+};
+
+struct nfulnl_msg_packet_hdr {
+	__be16		hw_protocol;	/* hw protocol (network order) */
+	u_int8_t	hook;		/* netfilter hook */
+	u_int8_t	_pad;
+};
+
+struct nfulnl_msg_packet_hw {
+	__be16		hw_addrlen;
+	u_int16_t	_pad;
+	u_int8_t	hw_addr[8];
+};
+
+struct nfulnl_msg_packet_timestamp {
+	aligned_be64	sec;
+	aligned_be64	usec;
+};
+
+enum nfulnl_attr_type {
+	NFULA_UNSPEC,
+	NFULA_PACKET_HDR,
+	NFULA_MARK,			/* u_int32_t nfmark */
+	NFULA_TIMESTAMP,		/* nfulnl_msg_packet_timestamp */
+	NFULA_IFINDEX_INDEV,		/* u_int32_t ifindex */
+	NFULA_IFINDEX_OUTDEV,		/* u_int32_t ifindex */
+	NFULA_IFINDEX_PHYSINDEV,	/* u_int32_t ifindex */
+	NFULA_IFINDEX_PHYSOUTDEV,	/* u_int32_t ifindex */
+	NFULA_HWADDR,			/* nfulnl_msg_packet_hw */
+	NFULA_PAYLOAD,			/* opaque data payload */
+	NFULA_PREFIX,			/* string prefix */
+	NFULA_UID,			/* user id of socket */
+	NFULA_SEQ,			/* instance-local sequence number */
+	NFULA_SEQ_GLOBAL,		/* global sequence number */
+
+	__NFULA_MAX
+};
+#define NFULA_MAX (__NFULA_MAX - 1)
+
+enum nfulnl_msg_config_cmds {
+	NFULNL_CFG_CMD_NONE,
+	NFULNL_CFG_CMD_BIND,
+	NFULNL_CFG_CMD_UNBIND,
+	NFULNL_CFG_CMD_PF_BIND,
+	NFULNL_CFG_CMD_PF_UNBIND,
+};
+
+struct nfulnl_msg_config_cmd {
+	u_int8_t	command;	/* nfulnl_msg_config_cmds */
+} __attribute__ ((packed));
+
+struct nfulnl_msg_config_mode {
+	__be32		copy_range;
+	u_int8_t	copy_mode;
+	u_int8_t	_pad;
+} __attribute__ ((packed));
+
+enum nfulnl_attr_config {
+	NFULA_CFG_UNSPEC,
+	NFULA_CFG_CMD,			/* nfulnl_msg_config_cmd */
+	NFULA_CFG_MODE,			/* nfulnl_msg_config_mode */
+	NFULA_CFG_NLBUFSIZ,		/* u_int32_t buffer size */
+	NFULA_CFG_TIMEOUT,		/* u_int32_t in 1/100 s */
+	NFULA_CFG_QTHRESH,		/* u_int32_t */
+	NFULA_CFG_FLAGS,		/* u_int16_t */
+	__NFULA_CFG_MAX
+};
+#define NFULA_CFG_MAX (__NFULA_CFG_MAX -1)
+
+#define NFULNL_COPY_NONE	0x00
+#define NFULNL_COPY_META	0x01
+#define NFULNL_COPY_PACKET	0x02
+
+#define NFULNL_CFG_F_SEQ	0x0001
+#define NFULNL_CFG_F_SEQ_GLOBAL	0x0002
+
+#endif /* _NFNETLINK_LOG_H */

  parent reply	other threads:[~2007-09-03  5:12 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-09-03  5:09 netfilter support in libnl Philip Craig
2007-09-03  5:11 ` [PATCH 1/3] libnl: add netfilter support Philip Craig
2007-09-03  9:50   ` Patrick McHardy
2007-09-03 10:01     ` Thomas Graf
2007-09-03 10:06       ` Patrick McHardy
2007-09-03 10:15         ` Thomas Graf
2007-09-03 10:53           ` Patrick McHardy
2007-09-03 11:03             ` Thomas Graf
2007-09-03 11:13               ` Patrick McHardy
2007-09-04  1:18     ` Philip Craig
2007-09-03 10:09   ` Thomas Graf
2007-09-04  2:12     ` Philip Craig
2007-09-04  9:39       ` Thomas Graf
2007-09-04 11:36   ` Thomas Graf
2007-09-03  5:11 ` [PATCH 2/3] libnl: add netfilter conntrack support Philip Craig
2007-09-04 16:45   ` Thomas Graf
2007-09-03  5:12 ` Philip Craig [this message]
2007-09-04 16:48   ` [PATCH 3/3] libnl: add netfilter log support Thomas Graf
2007-09-03  9:30 ` netfilter support in libnl Patrick McHardy
2007-09-03  9:59   ` Thomas Graf
2007-09-03 10:05     ` Patrick McHardy
2007-09-03 10:16       ` Thomas Graf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=46DB97C0.3060602@snapgear.com \
    --to=philipc@snapgear.com \
    --cc=netfilter-devel@lists.netfilter.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.