* [LIBNL 01/09]: Add if_vlan.h
2008-01-18 16:55 [LIBNL 00/09]: Netfilter update + minor fixes Patrick McHardy
@ 2008-01-18 16:55 ` Patrick McHardy
2008-02-07 11:50 ` Thomas Graf
2008-01-18 16:55 ` [LIBNL 02/09]: Fix minor memleaks on exit Patrick McHardy
` (7 subsequent siblings)
8 siblings, 1 reply; 26+ messages in thread
From: Patrick McHardy @ 2008-01-18 16:55 UTC (permalink / raw)
To: tgraf; +Cc: Patrick McHardy, netfilter-devel, philipc
commit 057316c354252ef6273f6deb4fe4232c02e4d141
Author: Patrick McHardy <kaber@trash.net>
Date: Fri Jan 18 16:15:53 2008 +0100
[LIBNL]: Add if_vlan.h
vlan support needs VLAN_FLAG_REORDER_HDR, which is not available in
older if_vlan.h versions. Add the current version from the kernel.
Signed-off-by: Patrick McHardy <kaber@trash.net>
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
new file mode 100644
index 0000000..a1dbeec
--- /dev/null
+++ b/include/linux/if_vlan.h
@@ -0,0 +1,61 @@
+/*
+ * VLAN An implementation of 802.1Q VLAN tagging.
+ *
+ * Authors: Ben Greear <greearb@candelatech.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef _LINUX_IF_VLAN_H_
+#define _LINUX_IF_VLAN_H_
+
+
+/* VLAN IOCTLs are found in sockios.h */
+
+/* Passed in vlan_ioctl_args structure to determine behaviour. */
+enum vlan_ioctl_cmds {
+ ADD_VLAN_CMD,
+ DEL_VLAN_CMD,
+ SET_VLAN_INGRESS_PRIORITY_CMD,
+ SET_VLAN_EGRESS_PRIORITY_CMD,
+ GET_VLAN_INGRESS_PRIORITY_CMD,
+ GET_VLAN_EGRESS_PRIORITY_CMD,
+ SET_VLAN_NAME_TYPE_CMD,
+ SET_VLAN_FLAG_CMD,
+ GET_VLAN_REALDEV_NAME_CMD, /* If this works, you know it's a VLAN device, btw */
+ GET_VLAN_VID_CMD /* Get the VID of this VLAN (specified by name) */
+};
+
+enum vlan_flags {
+ VLAN_FLAG_REORDER_HDR = 0x1,
+};
+
+enum vlan_name_types {
+ VLAN_NAME_TYPE_PLUS_VID, /* Name will look like: vlan0005 */
+ VLAN_NAME_TYPE_RAW_PLUS_VID, /* name will look like: eth1.0005 */
+ VLAN_NAME_TYPE_PLUS_VID_NO_PAD, /* Name will look like: vlan5 */
+ VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD, /* Name will look like: eth0.5 */
+ VLAN_NAME_TYPE_HIGHEST
+};
+
+struct vlan_ioctl_args {
+ int cmd; /* Should be one of the vlan_ioctl_cmds enum above. */
+ char device1[24];
+
+ union {
+ char device2[24];
+ int VID;
+ unsigned int skb_priority;
+ unsigned int name_type;
+ unsigned int bind_type;
+ unsigned int flag; /* Matches vlan_dev_info flags */
+ } u;
+
+ short vlan_qos;
+};
+
+#endif /* !(_LINUX_IF_VLAN_H_) */
^ permalink raw reply related [flat|nested] 26+ messages in thread* [LIBNL 02/09]: Fix minor memleaks on exit
2008-01-18 16:55 [LIBNL 00/09]: Netfilter update + minor fixes Patrick McHardy
2008-01-18 16:55 ` [LIBNL 01/09]: Add if_vlan.h Patrick McHardy
@ 2008-01-18 16:55 ` Patrick McHardy
2008-02-07 11:52 ` Thomas Graf
2008-01-18 16:55 ` [LIBNL 03/09]: Generic netfilter stuff Patrick McHardy
` (6 subsequent siblings)
8 siblings, 1 reply; 26+ messages in thread
From: Patrick McHardy @ 2008-01-18 16:55 UTC (permalink / raw)
To: tgraf; +Cc: Patrick McHardy, netfilter-devel, philipc
commit f3982f36f684c2ef1174bf3d951c15d3e5a91f9a
Author: Patrick McHardy <kaber@trash.net>
Date: Fri Jan 18 16:16:07 2008 +0100
[LIBNL]: Fix minor memleaks on exit
Make valgrind happy ...
Signed-off-by: Patrick McHardy <kaber@trash.net>
diff --git a/lib/route/route_utils.c b/lib/route/route_utils.c
index a12d169..1386cda 100644
--- a/lib/route/route_utils.c
+++ b/lib/route/route_utils.c
@@ -63,6 +63,11 @@ static void __init init_routing_table_names(void)
add_routing_table_name(RT_TABLE_LOCAL, "local");
};
+static void __exit release_routing_table_names(void)
+{
+ __trans_list_clear(&table_names);
+}
+
int rtnl_route_read_table_names(const char *path)
{
__trans_list_clear(&table_names);
@@ -104,6 +109,11 @@ static void __init init_proto_names(void)
add_proto_name(RTPROT_STATIC, "static");
};
+static void __exit release_proto_names(void)
+{
+ __trans_list_clear(&proto_names);
+}
+
int rtnl_route_read_protocol_names(const char *path)
{
__trans_list_clear(&proto_names);
^ permalink raw reply related [flat|nested] 26+ messages in thread* [LIBNL 03/09]: Generic netfilter stuff
2008-01-18 16:55 [LIBNL 00/09]: Netfilter update + minor fixes Patrick McHardy
2008-01-18 16:55 ` [LIBNL 01/09]: Add if_vlan.h Patrick McHardy
2008-01-18 16:55 ` [LIBNL 02/09]: Fix minor memleaks on exit Patrick McHardy
@ 2008-01-18 16:55 ` Patrick McHardy
2008-02-07 11:54 ` Thomas Graf
2008-01-18 16:55 ` [LIBNL 04/09]: Add nfnetlink_queue support Patrick McHardy
` (5 subsequent siblings)
8 siblings, 1 reply; 26+ messages in thread
From: Patrick McHardy @ 2008-01-18 16:55 UTC (permalink / raw)
To: tgraf; +Cc: Patrick McHardy, netfilter-devel, philipc
commit d0d52158ccf2b1d60f864e888f9bdb08c0bdae8b
Author: Patrick McHardy <kaber@trash.net>
Date: Fri Jan 18 16:17:18 2008 +0100
[LIBNL]: Generic netfilter stuff
Add some generic helper functions for netfilter.
Signed-off-by: Patrick McHardy <kaber@trash.net>
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
new file mode 100644
index 0000000..0750ca6
--- /dev/null
+++ b/include/linux/netfilter.h
@@ -0,0 +1,39 @@
+#ifndef __LINUX_NETFILTER_H
+#define __LINUX_NETFILTER_H
+
+
+/* Responses from hook functions. */
+#define NF_DROP 0
+#define NF_ACCEPT 1
+#define NF_STOLEN 2
+#define NF_QUEUE 3
+#define NF_REPEAT 4
+#define NF_STOP 5
+#define NF_MAX_VERDICT NF_STOP
+
+/* we overload the higher bits for encoding auxiliary data such as the queue
+ * number. Not nice, but better than additional function arguments. */
+#define NF_VERDICT_MASK 0x0000ffff
+#define NF_VERDICT_BITS 16
+
+#define NF_VERDICT_QMASK 0xffff0000
+#define NF_VERDICT_QBITS 16
+
+#define NF_QUEUE_NR(x) (((x << NF_VERDICT_QBITS) & NF_VERDICT_QMASK) | NF_QUEUE)
+
+/* only for userspace compatibility */
+/* Generic cache responses from hook functions.
+ <= 0x2000 is used for protocol-flags. */
+#define NFC_UNKNOWN 0x4000
+#define NFC_ALTERED 0x8000
+
+enum nf_inet_hooks {
+ NF_INET_PRE_ROUTING,
+ NF_INET_LOCAL_IN,
+ NF_INET_FORWARD,
+ NF_INET_LOCAL_OUT,
+ NF_INET_POST_ROUTING,
+ NF_INET_NUMHOOKS,
+};
+
+#endif /*__LINUX_NETFILTER_H*/
diff --git a/include/netlink/netfilter/netfilter.h b/include/netlink/netfilter/netfilter.h
new file mode 100644
index 0000000..dd3589c
--- /dev/null
+++ b/include/netlink/netfilter/netfilter.h
@@ -0,0 +1,31 @@
+/*
+ * netlink/netfilter/netfilter.h Netfilter generic functions
+ *
+ * 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) 2008 Patrick McHardy <kaber@trash.net>
+ */
+
+#ifndef NETLINK_NETFILTER_H_
+#define NETLINK_NETFILTER_H_
+
+#include <netlink/netlink.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern char * nfnl_verdict2str(unsigned int, char *, size_t);
+extern unsigned int nfnl_str2verdict(const char *);
+
+extern char * nfnl_inet_hook2str(unsigned int, char *, size_t);
+extern unsigned int nfnl_str2inet_hook(const char *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/netfilter/netfilter.c b/lib/netfilter/netfilter.c
new file mode 100644
index 0000000..f88b355
--- /dev/null
+++ b/lib/netfilter/netfilter.c
@@ -0,0 +1,53 @@
+/*
+ * lib/netfilter/netfilter.c Netfilter Generic Functions
+ *
+ * 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) 2008 Patrick McHardy <kaber@trash.net>
+ */
+
+#include <netlink-local.h>
+#include <netlink/netfilter/netfilter.h>
+#include <linux/netfilter.h>
+
+static struct trans_tbl nfnl_verdicts[] = {
+ __ADD(NF_DROP, NF_DROP)
+ __ADD(NF_ACCEPT, NF_ACCEPT)
+ __ADD(NF_STOLEN, NF_STOLEN)
+ __ADD(NF_QUEUE, NF_QUEUE)
+ __ADD(NF_REPEAT, NF_REPEAT)
+ __ADD(NF_STOP, NF_STOP)
+};
+
+char *nfnl_verdict2str(unsigned int verdict, char *buf, size_t len)
+{
+ return __type2str(verdict, buf, len, nfnl_verdicts,
+ ARRAY_SIZE(nfnl_verdicts));
+}
+
+unsigned int nfnl_str2verdict(const char *name)
+{
+ return __str2type(name, nfnl_verdicts, ARRAY_SIZE(nfnl_verdicts));
+}
+
+static struct trans_tbl nfnl_inet_hooks[] = {
+ __ADD(NF_INET_PRE_ROUTING, NF_INET_PREROUTING)
+ __ADD(NF_INET_LOCAL_IN, NF_INET_LOCAL_IN)
+ __ADD(NF_INET_FORWARD, NF_INET_FORWARD)
+ __ADD(NF_INET_LOCAL_OUT, NF_INET_LOCAL_OUT)
+ __ADD(NF_INET_POST_ROUTING, NF_INET_POST_ROUTING)
+};
+
+char *nfnl_inet_hook2str(unsigned int hook, char *buf, size_t len)
+{
+ return __type2str(hook, buf, len, nfnl_inet_hooks,
+ ARRAY_SIZE(nfnl_inet_hooks));
+}
+
+unsigned int nfnl_str2inet_hook(const char *name)
+{
+ return __str2type(name, nfnl_inet_hooks, ARRAY_SIZE(nfnl_inet_hooks));
+}
^ permalink raw reply related [flat|nested] 26+ messages in thread* [LIBNL 04/09]: Add nfnetlink_queue support
2008-01-18 16:55 [LIBNL 00/09]: Netfilter update + minor fixes Patrick McHardy
` (2 preceding siblings ...)
2008-01-18 16:55 ` [LIBNL 03/09]: Generic netfilter stuff Patrick McHardy
@ 2008-01-18 16:55 ` Patrick McHardy
2008-02-07 12:00 ` Thomas Graf
2008-01-18 16:55 ` [LIBNL 05/09]: nfnetlink_log: only set hwproto if not zero Patrick McHardy
` (4 subsequent siblings)
8 siblings, 1 reply; 26+ messages in thread
From: Patrick McHardy @ 2008-01-18 16:55 UTC (permalink / raw)
To: tgraf; +Cc: Patrick McHardy, netfilter-devel, philipc
commit 1782a5fba82778d0d10838f511f57b2b2b70966a
Author: Patrick McHardy <kaber@trash.net>
Date: Fri Jan 18 17:44:08 2008 +0100
[LIBNL]: Add nfnetlink_queue support
Signed-off-by: Patrick McHardy <kaber@trash.net>
diff --git a/include/linux/netfilter/nfnetlink_queue.h b/include/linux/netfilter/nfnetlink_queue.h
new file mode 100644
index 0000000..bf7cfb6
--- /dev/null
+++ b/include/linux/netfilter/nfnetlink_queue.h
@@ -0,0 +1,94 @@
+#ifndef _NFNETLINK_QUEUE_H
+#define _NFNETLINK_QUEUE_H
+
+#include <linux/types.h>
+#include <linux/netfilter/nfnetlink.h>
+
+#ifndef aligned_be64
+#define aligned_be64 u_int64_t __attribute__((aligned(8)))
+#endif
+
+enum nfqnl_msg_types {
+ NFQNL_MSG_PACKET, /* packet from kernel to userspace */
+ NFQNL_MSG_VERDICT, /* verdict from userspace to kernel */
+ NFQNL_MSG_CONFIG, /* connect to a particular queue */
+
+ NFQNL_MSG_MAX
+};
+
+struct nfqnl_msg_packet_hdr {
+ __be32 packet_id; /* unique ID of packet in queue */
+ __be16 hw_protocol; /* hw protocol (network order) */
+ u_int8_t hook; /* netfilter hook */
+} __attribute__ ((packed));
+
+struct nfqnl_msg_packet_hw {
+ __be16 hw_addrlen;
+ u_int16_t _pad;
+ u_int8_t hw_addr[8];
+};
+
+struct nfqnl_msg_packet_timestamp {
+ aligned_be64 sec;
+ aligned_be64 usec;
+};
+
+enum nfqnl_attr_type {
+ NFQA_UNSPEC,
+ NFQA_PACKET_HDR,
+ NFQA_VERDICT_HDR, /* nfqnl_msg_verdict_hrd */
+ NFQA_MARK, /* u_int32_t nfmark */
+ NFQA_TIMESTAMP, /* nfqnl_msg_packet_timestamp */
+ NFQA_IFINDEX_INDEV, /* u_int32_t ifindex */
+ NFQA_IFINDEX_OUTDEV, /* u_int32_t ifindex */
+ NFQA_IFINDEX_PHYSINDEV, /* u_int32_t ifindex */
+ NFQA_IFINDEX_PHYSOUTDEV, /* u_int32_t ifindex */
+ NFQA_HWADDR, /* nfqnl_msg_packet_hw */
+ NFQA_PAYLOAD, /* opaque data payload */
+
+ __NFQA_MAX
+};
+#define NFQA_MAX (__NFQA_MAX - 1)
+
+struct nfqnl_msg_verdict_hdr {
+ __be32 verdict;
+ __be32 id;
+};
+
+
+enum nfqnl_msg_config_cmds {
+ NFQNL_CFG_CMD_NONE,
+ NFQNL_CFG_CMD_BIND,
+ NFQNL_CFG_CMD_UNBIND,
+ NFQNL_CFG_CMD_PF_BIND,
+ NFQNL_CFG_CMD_PF_UNBIND,
+};
+
+struct nfqnl_msg_config_cmd {
+ u_int8_t command; /* nfqnl_msg_config_cmds */
+ u_int8_t _pad;
+ __be16 pf; /* AF_xxx for PF_[UN]BIND */
+};
+
+enum nfqnl_config_mode {
+ NFQNL_COPY_NONE,
+ NFQNL_COPY_META,
+ NFQNL_COPY_PACKET,
+};
+
+struct nfqnl_msg_config_params {
+ __be32 copy_range;
+ u_int8_t copy_mode; /* enum nfqnl_config_mode */
+} __attribute__ ((packed));
+
+
+enum nfqnl_attr_config {
+ NFQA_CFG_UNSPEC,
+ NFQA_CFG_CMD, /* nfqnl_msg_config_cmd */
+ NFQA_CFG_PARAMS, /* nfqnl_msg_config_params */
+ NFQA_CFG_QUEUE_MAXLEN, /* u_int32_t */
+ __NFQA_CFG_MAX
+};
+#define NFQA_CFG_MAX (__NFQA_CFG_MAX-1)
+
+#endif /* _NFNETLINK_QUEUE_H */
diff --git a/include/netlink-types.h b/include/netlink-types.h
index f7c6437..f7bddca 100644
--- a/include/netlink-types.h
+++ b/include/netlink-types.h
@@ -755,4 +755,34 @@ struct nfnl_log {
uint32_t log_seq_global;
};
+struct nfnl_queue {
+ NLHDR_COMMON
+
+ uint16_t queue_group;
+ uint32_t queue_maxlen;
+ uint32_t queue_copy_range;
+ uint8_t queue_copy_mode;
+};
+
+struct nfnl_queue_msg {
+ NLHDR_COMMON
+
+ uint16_t queue_msg_group;
+ uint8_t queue_msg_family;
+ uint8_t queue_msg_hook;
+ uint16_t queue_msg_hwproto;
+ uint32_t queue_msg_packetid;
+ uint32_t queue_msg_mark;
+ struct timeval queue_msg_timestamp;
+ uint32_t queue_msg_indev;
+ uint32_t queue_msg_outdev;
+ uint32_t queue_msg_physindev;
+ uint32_t queue_msg_physoutdev;
+ uint8_t queue_msg_hwaddr[8];
+ int queue_msg_hwaddr_len;
+ void * queue_msg_payload;
+ int queue_msg_payload_len;
+ uint32_t queue_msg_verdict;
+};
+
#endif
diff --git a/include/netlink/netfilter/queue.h b/include/netlink/netfilter/queue.h
new file mode 100644
index 0000000..c88abe2
--- /dev/null
+++ b/include/netlink/netfilter/queue.h
@@ -0,0 +1,86 @@
+/*
+ * netlink/netfilter/queue.h Netfilter Queue
+ *
+ * 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) 2007, 2008 Patrick McHardy <kaber@trash.net>
+ */
+
+#ifndef NETLINK_QUEUE_H_
+#define NETLINK_QUEUE_H_
+
+#include <netlink/netlink.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct nl_handle;
+struct nlmsghdr;
+struct nfnl_queue;
+
+extern struct nl_object_ops queue_obj_ops;
+
+enum nfnl_queue_copy_mode {
+ NFNL_QUEUE_COPY_NONE,
+ NFNL_QUEUE_COPY_META,
+ NFNL_QUEUE_COPY_PACKET,
+};
+
+/* General */
+extern struct nfnl_queue * nfnl_queue_alloc(void);
+
+extern void nfnl_queue_get(struct nfnl_queue *);
+extern void nfnl_queue_put(struct nfnl_queue *);
+
+/* Attributes */
+extern void nfnl_queue_set_group(struct nfnl_queue *, uint16_t);
+extern int nfnl_queue_test_group(const struct nfnl_queue *);
+extern uint16_t nfnl_queue_get_group(const struct nfnl_queue *);
+
+extern void nfnl_queue_set_maxlen(struct nfnl_queue *, uint32_t);
+extern int nfnl_queue_test_maxlen(const struct nfnl_queue *);
+extern uint32_t nfnl_queue_get_maxlen(const struct nfnl_queue *);
+
+extern void nfnl_queue_set_copy_mode(struct nfnl_queue *,
+ enum nfnl_queue_copy_mode);
+extern int nfnl_queue_test_copy_mode(const struct nfnl_queue *);
+extern enum nfnl_queue_copy_mode nfnl_queue_get_copy_mode(const struct nfnl_queue *);
+
+extern char * nfnl_queue_copy_mode2str(enum nfnl_queue_copy_mode,
+ char *, size_t);
+extern enum nfnl_queue_copy_mode nfnl_queue_str2copy_mode(const char *);
+
+extern void nfnl_queue_set_copy_range(struct nfnl_queue *,
+ uint32_t);
+extern int nfnl_queue_test_copy_range(const struct nfnl_queue *);
+extern uint32_t nfnl_queue_get_copy_range(const struct nfnl_queue *);
+
+/* Message construction / sending */
+extern struct nl_msg * nfnl_queue_build_pf_bind(uint8_t);
+extern int nfnl_queue_pf_bind(struct nl_handle *, uint8_t);
+
+extern struct nl_msg * nfnl_queue_build_pf_unbind(uint8_t);
+extern int nfnl_queue_pf_unbind(struct nl_handle *, uint8_t);
+
+extern struct nl_msg * nfnl_queue_build_create_request(const struct nfnl_queue *);
+extern int nfnl_queue_create(struct nl_handle *,
+ const struct nfnl_queue *);
+
+extern struct nl_msg * nfnl_queue_build_change_request(const struct nfnl_queue *);
+extern int nfnl_queue_change(struct nl_handle *,
+ const struct nfnl_queue *);
+
+extern struct nl_msg * nfnl_queue_build_delete_request(const struct nfnl_queue *);
+extern int nfnl_queue_delete(struct nl_handle *,
+ const struct nfnl_queue *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/include/netlink/netfilter/queue_msg.h b/include/netlink/netfilter/queue_msg.h
new file mode 100644
index 0000000..daf7b3c
--- /dev/null
+++ b/include/netlink/netfilter/queue_msg.h
@@ -0,0 +1,101 @@
+/*
+ * netlink/netfilter/queue_msg.h Netfilter Queue Messages
+ *
+ * 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) 2007, 2008 Patrick McHardy <kaber@trash.net>
+ */
+
+#ifndef NETLINK_QUEUE_MSG_H_
+#define NETLINK_QUEUE_MSG_H_
+
+#include <netlink/netlink.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct nl_handle;
+struct nlmsghdr;
+struct nfnl_queue_msg;
+
+extern struct nl_object_ops queue_msg_obj_ops;
+
+/* General */
+extern struct nfnl_queue_msg * nfnl_queue_msg_alloc(void);
+extern struct nfnl_queue_msg * nfnlmsg_queue_msg_parse(struct nlmsghdr *);
+
+extern void nfnl_queue_msg_get(struct nfnl_queue_msg *);
+extern void nfnl_queue_msg_put(struct nfnl_queue_msg *);
+
+extern void nfnl_queue_msg_set_group(struct nfnl_queue_msg *, uint16_t);
+extern int nfnl_queue_msg_test_group(const struct nfnl_queue_msg *);
+extern uint16_t nfnl_queue_msg_get_group(const struct nfnl_queue_msg *);
+
+extern void nfnl_queue_msg_set_family(struct nfnl_queue_msg *, uint8_t);
+extern int nfnl_queue_msg_test_family(const struct nfnl_queue_msg *);
+extern uint8_t nfnl_queue_msg_get_family(const struct nfnl_queue_msg *);
+
+extern void nfnl_queue_msg_set_packetid(struct nfnl_queue_msg *, uint32_t);
+extern int nfnl_queue_msg_test_packetid(const struct nfnl_queue_msg *);
+extern uint16_t nfnl_queue_msg_get_packetid(const struct nfnl_queue_msg *);
+
+extern void nfnl_queue_msg_set_hwproto(struct nfnl_queue_msg *, uint16_t);
+extern int nfnl_queue_msg_test_hwproto(const struct nfnl_queue_msg *);
+extern uint16_t nfnl_queue_msg_get_hwproto(const struct nfnl_queue_msg *);
+
+extern void nfnl_queue_msg_set_hook(struct nfnl_queue_msg *, uint8_t);
+extern int nfnl_queue_msg_test_hook(const struct nfnl_queue_msg *);
+extern uint8_t nfnl_queue_msg_get_hook(const struct nfnl_queue_msg *);
+
+extern void nfnl_queue_msg_set_mark(struct nfnl_queue_msg *, uint32_t);
+extern int nfnl_queue_msg_test_mark(const struct nfnl_queue_msg *);
+extern uint32_t nfnl_queue_msg_get_mark(const struct nfnl_queue_msg *);
+
+extern void nfnl_queue_msg_set_timestamp(struct nfnl_queue_msg *,
+ struct timeval *);
+extern int nfnl_queue_msg_test_timestamp(const struct nfnl_queue_msg *);
+extern const struct timeval * nfnl_queue_msg_get_timestamp(const struct nfnl_queue_msg *);
+
+extern void nfnl_queue_msg_set_indev(struct nfnl_queue_msg *, uint32_t);
+extern int nfnl_queue_msg_test_indev(const struct nfnl_queue_msg *);
+extern uint32_t nfnl_queue_msg_get_indev(const struct nfnl_queue_msg *);
+
+extern void nfnl_queue_msg_set_outdev(struct nfnl_queue_msg *, uint32_t);
+extern int nfnl_queue_msg_test_outdev(const struct nfnl_queue_msg *);
+extern uint32_t nfnl_queue_msg_get_outdev(const struct nfnl_queue_msg *);
+
+extern void nfnl_queue_msg_set_physindev(struct nfnl_queue_msg *, uint32_t);
+extern int nfnl_queue_msg_test_physindev(const struct nfnl_queue_msg *);
+extern uint32_t nfnl_queue_msg_get_physindev(const struct nfnl_queue_msg *);
+
+extern void nfnl_queue_msg_set_physoutdev(struct nfnl_queue_msg *, uint32_t);
+extern int nfnl_queue_msg_test_physoutdev(const struct nfnl_queue_msg *);
+extern uint32_t nfnl_queue_msg_get_physoutdev(const struct nfnl_queue_msg *);
+
+extern void nfnl_queue_msg_set_hwaddr(struct nfnl_queue_msg *, uint8_t *, int);
+extern int nfnl_queue_msg_test_hwaddr(const struct nfnl_queue_msg *);
+extern const uint8_t * nfnl_queue_msg_get_hwaddr(const struct nfnl_queue_msg *, int *);
+
+extern int nfnl_queue_msg_set_payload(struct nfnl_queue_msg *, uint8_t *, int);
+extern int nfnl_queue_msg_test_payload(const struct nfnl_queue_msg *);
+extern const void * nfnl_queue_msg_get_payload(const struct nfnl_queue_msg *, int *);
+
+extern void nfnl_queue_msg_set_verdict(struct nfnl_queue_msg *,
+ unsigned int);
+extern int nfnl_queue_msg_test_verdict(const struct nfnl_queue_msg *);
+extern unsigned int nfnl_queue_msg_get_verdict(const struct nfnl_queue_msg *);
+
+extern struct nl_msg * nfnl_queue_msg_build_verdict(const struct nfnl_queue_msg *);
+extern int nfnl_queue_msg_send_verdict(struct nl_handle *,
+ const struct nfnl_queue_msg *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/lib/netfilter/queue.c b/lib/netfilter/queue.c
new file mode 100644
index 0000000..c056eef
--- /dev/null
+++ b/lib/netfilter/queue.c
@@ -0,0 +1,233 @@
+/*
+ * lib/netfilter/queue.c Netfilter Queue
+ *
+ * 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) 2007, 2008 Patrick McHardy <kaber@trash.net>
+ */
+
+/**
+ * @ingroup nfnl
+ * @defgroup queue Queue
+ * @brief
+ * @{
+ */
+
+#include <sys/types.h>
+#include <linux/netfilter/nfnetlink_queue.h>
+
+#include <netlink-local.h>
+#include <netlink/attr.h>
+#include <netlink/netfilter/nfnl.h>
+#include <netlink/netfilter/queue.h>
+
+static int send_queue_request(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);
+}
+
+/**
+ * @name Queue Commands
+ * @{
+ */
+
+static struct nl_msg *build_queue_cmd_request(uint8_t family, uint16_t queuenum,
+ uint8_t command)
+{
+ struct nl_msg *msg;
+ struct nfqnl_msg_config_cmd cmd;
+
+ msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_QUEUE, NFQNL_MSG_CONFIG, 0,
+ family, queuenum);
+ if (msg == NULL)
+ return NULL;
+
+ cmd.pf = htons(family);
+ cmd._pad = 0;
+ cmd.command = command;
+ if (nla_put(msg, NFQA_CFG_CMD, sizeof(cmd), &cmd) < 0)
+ goto nla_put_failure;
+
+ return msg;
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return NULL;
+}
+
+struct nl_msg *nfnl_queue_build_pf_bind(uint8_t pf)
+{
+ return build_queue_cmd_request(pf, 0, NFQNL_CFG_CMD_PF_BIND);
+}
+
+int nfnl_queue_pf_bind(struct nl_handle *nlh, uint8_t pf)
+{
+ struct nl_msg *msg;
+
+ msg = nfnl_queue_build_pf_bind(pf);
+ if (!msg)
+ return nl_get_errno();
+
+ return send_queue_request(nlh, msg);
+}
+
+struct nl_msg *nfnl_queue_build_pf_unbind(uint8_t pf)
+{
+ return build_queue_cmd_request(pf, 0, NFQNL_CFG_CMD_PF_UNBIND);
+}
+
+int nfnl_queue_pf_unbind(struct nl_handle *nlh, uint8_t pf)
+{
+ struct nl_msg *msg;
+
+ msg = nfnl_queue_build_pf_unbind(pf);
+ if (!msg)
+ return nl_get_errno();
+
+ return send_queue_request(nlh, msg);
+}
+
+static struct nl_msg *nfnl_queue_build_request(const struct nfnl_queue *queue)
+{
+ struct nl_msg *msg;
+
+ if (!nfnl_queue_test_group(queue))
+ return NULL;
+
+ msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_QUEUE, NFQNL_MSG_CONFIG, 0,
+ 0, nfnl_queue_get_group(queue));
+ if (msg == NULL)
+ return NULL;
+
+ if (nfnl_queue_test_maxlen(queue) &&
+ nla_put_u32(msg, NFQA_CFG_QUEUE_MAXLEN,
+ htonl(nfnl_queue_get_maxlen(queue))) < 0)
+ goto nla_put_failure;
+
+ /* This sucks, the nfnetlink_queue interface always expects both
+ * parameters to be present. Needs to be done properly.
+ */
+ if (nfnl_queue_test_copy_mode(queue)) {
+ struct nfqnl_msg_config_params params;
+
+ switch (nfnl_queue_get_copy_mode(queue)) {
+ case NFNL_QUEUE_COPY_NONE:
+ params.copy_mode = NFQNL_COPY_NONE;
+ break;
+ case NFNL_QUEUE_COPY_META:
+ params.copy_mode = NFQNL_COPY_META;
+ break;
+ case NFNL_QUEUE_COPY_PACKET:
+ params.copy_mode = NFQNL_COPY_PACKET;
+ break;
+ }
+ params.copy_range = htonl(nfnl_queue_get_copy_range(queue));
+
+ if (nla_put(msg, NFQA_CFG_PARAMS, sizeof(params), ¶ms) < 0)
+ goto nla_put_failure;
+ }
+ return msg;
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return NULL;
+}
+
+struct nl_msg *nfnl_queue_build_create_request(const struct nfnl_queue *queue)
+{
+ struct nl_msg *msg;
+ struct nfqnl_msg_config_cmd cmd;
+
+ msg = nfnl_queue_build_request(queue);
+ if (msg == NULL)
+ return NULL;
+
+ cmd.pf = 0;
+ cmd._pad = 0;
+ cmd.command = NFQNL_CFG_CMD_BIND;
+
+ if (nla_put(msg, NFQA_CFG_CMD, sizeof(cmd), &cmd) < 0)
+ goto nla_put_failure;
+
+ return msg;
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return NULL;
+}
+
+int nfnl_queue_create(struct nl_handle *nlh, const struct nfnl_queue *queue)
+{
+ struct nl_msg *msg;
+
+ msg = nfnl_queue_build_create_request(queue);
+ if (msg == NULL)
+ return nl_errno(ENOMEM);
+
+ return send_queue_request(nlh, msg);
+}
+
+struct nl_msg *nfnl_queue_build_change_request(const struct nfnl_queue *queue)
+{
+ return nfnl_queue_build_request(queue);
+}
+
+int nfnl_queue_change(struct nl_handle *nlh, const struct nfnl_queue *queue)
+{
+ struct nl_msg *msg;
+
+ msg = nfnl_queue_build_change_request(queue);
+ if (msg == NULL)
+ return nl_errno(ENOMEM);
+
+ return send_queue_request(nlh, msg);
+}
+
+struct nl_msg *nfnl_queue_build_delete_request(const struct nfnl_queue *queue)
+{
+ if (!nfnl_queue_test_group(queue))
+ return NULL;
+
+ return build_queue_cmd_request(0, nfnl_queue_get_group(queue),
+ NFQNL_CFG_CMD_UNBIND);
+}
+
+int nfnl_queue_delete(struct nl_handle *nlh, const struct nfnl_queue *queue)
+{
+ struct nl_msg *msg;
+
+ msg = nfnl_queue_build_delete_request(queue);
+ if (msg == NULL)
+ return nl_errno(ENOMEM);
+
+ return send_queue_request(nlh, msg);
+}
+
+/** @} */
+
+static struct nl_cache_ops nfnl_queue_ops = {
+ .co_name = "netfilter/queue",
+ .co_obj_ops = &queue_obj_ops,
+};
+
+static void __init nfnl_queue_init(void)
+{
+ nl_cache_mngt_register(&nfnl_queue_ops);
+}
+
+static void __exit nfnl_queue_exit(void)
+{
+ nl_cache_mngt_unregister(&nfnl_queue_ops);
+}
+
+/** @} */
diff --git a/lib/netfilter/queue_msg.c b/lib/netfilter/queue_msg.c
new file mode 100644
index 0000000..82e79a6
--- /dev/null
+++ b/lib/netfilter/queue_msg.c
@@ -0,0 +1,240 @@
+/*
+ * lib/netfilter/queue_msg.c Netfilter Queue Messages
+ *
+ * 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) 2007, 2008 Patrick McHardy <kaber@trash.net>
+ */
+
+/**
+ * @ingroup nfnl
+ * @defgroup queue Queue
+ * @brief
+ * @{
+ */
+
+#include <sys/types.h>
+#include <linux/netfilter/nfnetlink_queue.h>
+
+#include <netlink-local.h>
+#include <netlink/attr.h>
+#include <netlink/netfilter/nfnl.h>
+#include <netlink/netfilter/queue_msg.h>
+
+static struct nl_cache_ops nfnl_queue_msg_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 queue_policy[NFQA_MAX+1] = {
+ [NFQA_PACKET_HDR] = {
+ .minlen = sizeof(struct nfqnl_msg_packet_hdr),
+ },
+ [NFQA_VERDICT_HDR] = {
+ .minlen = sizeof(struct nfqnl_msg_verdict_hdr),
+ },
+ [NFQA_MARK] = { .type = NLA_U32 },
+ [NFQA_TIMESTAMP] = {
+ .minlen = sizeof(struct nfqnl_msg_packet_timestamp),
+ },
+ [NFQA_IFINDEX_INDEV] = { .type = NLA_U32 },
+ [NFQA_IFINDEX_OUTDEV] = { .type = NLA_U32 },
+ [NFQA_IFINDEX_PHYSINDEV] = { .type = NLA_U32 },
+ [NFQA_IFINDEX_PHYSOUTDEV] = { .type = NLA_U32 },
+ [NFQA_HWADDR] = {
+ .minlen = sizeof(struct nfqnl_msg_packet_timestamp),
+ },
+};
+
+struct nfnl_queue_msg *nfnlmsg_queue_msg_parse(struct nlmsghdr *nlh)
+{
+ struct nfnl_queue_msg *msg;
+ struct nlattr *tb[NFQA_MAX+1];
+ struct nlattr *attr;
+ int err;
+
+ msg = nfnl_queue_msg_alloc();
+ if (!msg)
+ return NULL;
+
+ msg->ce_msgtype = nlh->nlmsg_type;
+
+ err = nlmsg_parse(nlh, sizeof(struct nfgenmsg), tb, NFQA_MAX,
+ queue_policy);
+ if (err < 0)
+ goto errout;
+
+ nfnl_queue_msg_set_group(msg, nfnlmsg_res_id(nlh));
+ nfnl_queue_msg_set_family(msg, nfnlmsg_family(nlh));
+
+ attr = tb[NFQA_PACKET_HDR];
+ if (attr) {
+ struct nfqnl_msg_packet_hdr *hdr = nla_data(attr);
+
+ nfnl_queue_msg_set_packetid(msg, ntohl(hdr->packet_id));
+ if (hdr->hw_protocol)
+ nfnl_queue_msg_set_hwproto(msg, hdr->hw_protocol);
+ nfnl_queue_msg_set_hook(msg, hdr->hook);
+ }
+
+ attr = tb[NFQA_MARK];
+ if (attr)
+ nfnl_queue_msg_set_mark(msg, ntohl(nla_get_u32(attr)));
+
+ attr = tb[NFQA_TIMESTAMP];
+ if (attr) {
+ struct nfqnl_msg_packet_timestamp *timestamp = nla_data(attr);
+ struct timeval tv;
+
+ tv.tv_sec = ntohll(timestamp->sec);
+ tv.tv_usec = ntohll(timestamp->usec);
+ nfnl_queue_msg_set_timestamp(msg, &tv);
+ }
+
+ attr = tb[NFQA_IFINDEX_INDEV];
+ if (attr)
+ nfnl_queue_msg_set_indev(msg, ntohl(nla_get_u32(attr)));
+
+ attr = tb[NFQA_IFINDEX_OUTDEV];
+ if (attr)
+ nfnl_queue_msg_set_outdev(msg, ntohl(nla_get_u32(attr)));
+
+ attr = tb[NFQA_IFINDEX_PHYSINDEV];
+ if (attr)
+ nfnl_queue_msg_set_physindev(msg, ntohl(nla_get_u32(attr)));
+
+ attr = tb[NFQA_IFINDEX_PHYSOUTDEV];
+ if (attr)
+ nfnl_queue_msg_set_physoutdev(msg, ntohl(nla_get_u32(attr)));
+
+ attr = tb[NFQA_HWADDR];
+ if (attr) {
+ struct nfqnl_msg_packet_hw *hw = nla_data(attr);
+
+ nfnl_queue_msg_set_hwaddr(msg, hw->hw_addr,
+ ntohs(hw->hw_addrlen));
+ }
+
+ attr = tb[NFQA_PAYLOAD];
+ if (attr) {
+ err = nfnl_queue_msg_set_payload(msg, nla_data(attr),
+ nla_len(attr));
+ if (err < 0)
+ goto errout;
+ }
+
+ return msg;
+
+errout:
+ nfnl_queue_msg_put(msg);
+ return NULL;
+}
+
+static int queue_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
+ struct nlmsghdr *nlh, struct nl_parser_param *pp)
+{
+ struct nfnl_queue_msg *msg;
+ int err;
+
+ msg = nfnlmsg_queue_msg_parse(nlh);
+ if (msg == NULL)
+ goto errout_errno;
+
+ err = pp->pp_cb((struct nl_object *) msg, pp);
+ if (err < 0)
+ goto errout;
+
+ err = P_ACCEPT;
+
+errout:
+ nfnl_queue_msg_put(msg);
+ return err;
+
+errout_errno:
+ err = nl_get_errno();
+ goto errout;
+}
+
+/** @} */
+
+struct nl_msg *nfnl_queue_msg_build_verdict(const struct nfnl_queue_msg *msg)
+{
+ struct nl_msg *nlmsg;
+ struct nfqnl_msg_verdict_hdr verdict;
+
+ nlmsg = nfnlmsg_alloc_simple(NFNL_SUBSYS_QUEUE, NFQNL_MSG_VERDICT, 0,
+ nfnl_queue_msg_get_family(msg),
+ nfnl_queue_msg_get_group(msg));
+ if (nlmsg == NULL)
+ return NULL;
+
+ verdict.id = htonl(nfnl_queue_msg_get_packetid(msg));
+ verdict.verdict = htonl(nfnl_queue_msg_get_verdict(msg));
+ if (nla_put(nlmsg, NFQA_VERDICT_HDR, sizeof(verdict), &verdict) < 0)
+ goto nla_put_failure;
+
+ if (nfnl_queue_msg_test_mark(msg) &&
+ nla_put_u32(nlmsg, NFQA_MARK,
+ ntohl(nfnl_queue_msg_get_mark(msg))) < 0)
+ goto nla_put_failure;
+
+ return nlmsg;
+
+nla_put_failure:
+ nlmsg_free(nlmsg);
+ return NULL;
+}
+
+int nfnl_queue_msg_send_verdict(struct nl_handle *nlh,
+ const struct nfnl_queue_msg *msg)
+{
+ struct nl_msg *nlmsg;
+ int err;
+
+ nlmsg = nfnl_queue_msg_build_verdict(msg);
+ if (nlmsg == NULL)
+ return nl_errno(ENOMEM);
+
+ err = nl_send_auto_complete(nlh, nlmsg);
+ nlmsg_free(nlmsg);
+ if (err < 0)
+ return err;
+ return nl_wait_for_ack(nlh);
+}
+
+#define NFNLMSG_QUEUE_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_QUEUE, (type))
+static struct nl_cache_ops nfnl_queue_msg_ops = {
+ .co_name = "netfilter/queue_msg",
+ .co_hdrsize = NFNL_HDRLEN,
+ .co_msgtypes = {
+ { NFNLMSG_QUEUE_TYPE(NFQNL_MSG_PACKET), NL_ACT_NEW, "new" },
+ END_OF_MSGTYPES_LIST,
+ },
+ .co_protocol = NETLINK_NETFILTER,
+ .co_msg_parser = queue_msg_parser,
+ .co_obj_ops = &queue_msg_obj_ops,
+};
+
+static void __init nfnl_msg_queue_init(void)
+{
+ nl_cache_mngt_register(&nfnl_queue_msg_ops);
+}
+
+static void __exit nfnl_queue_msg_exit(void)
+{
+ nl_cache_mngt_unregister(&nfnl_queue_msg_ops);
+}
+
+/** @} */
diff --git a/lib/netfilter/queue_msg_obj.c b/lib/netfilter/queue_msg_obj.c
new file mode 100644
index 0000000..f86d6f6
--- /dev/null
+++ b/lib/netfilter/queue_msg_obj.c
@@ -0,0 +1,480 @@
+/*
+ * lib/netfilter/queue_msg_obj.c Netfilter Queue Message 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) 2007, 2008 Patrick McHardy <kaber@trash.net>
+ */
+
+#include <netlink-local.h>
+#include <netlink/netfilter/nfnl.h>
+#include <netlink/netfilter/netfilter.h>
+#include <netlink/netfilter/queue_msg.h>
+#include <linux/netfilter.h>
+
+/** @cond SKIP */
+#define QUEUE_MSG_ATTR_GROUP (1UL << 0)
+#define QUEUE_MSG_ATTR_FAMILY (1UL << 1)
+#define QUEUE_MSG_ATTR_PACKETID (1UL << 2)
+#define QUEUE_MSG_ATTR_HWPROTO (1UL << 3)
+#define QUEUE_MSG_ATTR_HOOK (1UL << 4)
+#define QUEUE_MSG_ATTR_MARK (1UL << 5)
+#define QUEUE_MSG_ATTR_TIMESTAMP (1UL << 6)
+#define QUEUE_MSG_ATTR_INDEV (1UL << 7)
+#define QUEUE_MSG_ATTR_OUTDEV (1UL << 8)
+#define QUEUE_MSG_ATTR_PHYSINDEV (1UL << 9)
+#define QUEUE_MSG_ATTR_PHYSOUTDEV (1UL << 10)
+#define QUEUE_MSG_ATTR_HWADDR (1UL << 11)
+#define QUEUE_MSG_ATTR_PAYLOAD (1UL << 12)
+#define QUEUE_MSG_ATTR_VERDICT (1UL << 13)
+/** @endcond */
+
+static void nfnl_queue_msg_free_data(struct nl_object *c)
+{
+ struct nfnl_queue_msg *msg = (struct nfnl_queue_msg *) c;
+
+ if (msg == NULL)
+ return;
+
+ free(msg->queue_msg_payload);
+}
+
+static int nfnl_queue_msg_clone(struct nl_object *_dst, struct nl_object *_src)
+{
+ struct nfnl_queue_msg *dst = (struct nfnl_queue_msg *) _dst;
+ struct nfnl_queue_msg *src = (struct nfnl_queue_msg *) _src;
+ int err;
+
+ if (src->queue_msg_payload) {
+ err = nfnl_queue_msg_set_payload(dst, src->queue_msg_payload,
+ src->queue_msg_payload_len);
+ if (err < 0)
+ goto errout;
+ }
+
+ return 0;
+errout:
+ return err;
+}
+
+static int nfnl_queue_msg_dump(struct nl_object *a, struct nl_dump_params *p)
+{
+ struct nfnl_queue_msg *msg = (struct nfnl_queue_msg *) a;
+ struct nl_cache *link_cache;
+ char buf[64];
+
+ link_cache = nl_cache_mngt_require("route/link");
+
+ if (msg->ce_mask & QUEUE_MSG_ATTR_GROUP)
+ dp_dump(p, "GROUP=%u ", msg->queue_msg_group);
+
+ if (msg->ce_mask & QUEUE_MSG_ATTR_INDEV) {
+ if (link_cache)
+ dp_dump(p, "IN=%s ",
+ rtnl_link_i2name(link_cache,
+ msg->queue_msg_indev,
+ buf, sizeof(buf)));
+ else
+ dp_dump(p, "IN=%d ", msg->queue_msg_indev);
+ }
+
+ if (msg->ce_mask & QUEUE_MSG_ATTR_PHYSINDEV) {
+ if (link_cache)
+ dp_dump(p, "PHYSIN=%s ",
+ rtnl_link_i2name(link_cache,
+ msg->queue_msg_physindev,
+ buf, sizeof(buf)));
+ else
+ dp_dump(p, "IN=%d ", msg->queue_msg_physindev);
+ }
+
+ if (msg->ce_mask & QUEUE_MSG_ATTR_OUTDEV) {
+ if (link_cache)
+ dp_dump(p, "OUT=%s ",
+ rtnl_link_i2name(link_cache,
+ msg->queue_msg_outdev,
+ buf, sizeof(buf)));
+ else
+ dp_dump(p, "OUT=%d ", msg->queue_msg_outdev);
+ }
+
+ if (msg->ce_mask & QUEUE_MSG_ATTR_PHYSOUTDEV) {
+ if (link_cache)
+ dp_dump(p, "PHYSOUT=%s ",
+ rtnl_link_i2name(link_cache,
+ msg->queue_msg_physoutdev,
+ buf, sizeof(buf)));
+ else
+ dp_dump(p, "PHYSOUT=%d ", msg->queue_msg_physoutdev);
+ }
+
+ if (msg->ce_mask & QUEUE_MSG_ATTR_HWADDR) {
+ int i;
+
+ dp_dump(p, "MAC");
+ for (i = 0; i < msg->queue_msg_hwaddr_len; i++)
+ dp_dump(p, "%c%02x", i?':':'=',
+ msg->queue_msg_hwaddr[i]);
+ dp_dump(p, " ");
+ }
+
+ if (msg->ce_mask & QUEUE_MSG_ATTR_FAMILY)
+ dp_dump(p, "FAMILY=%s ",
+ nl_af2str(msg->queue_msg_family, buf, sizeof(buf)));
+
+ if (msg->ce_mask & QUEUE_MSG_ATTR_HWPROTO)
+ dp_dump(p, "HWPROTO=%s ",
+ nl_ether_proto2str(ntohs(msg->queue_msg_hwproto),
+ buf, sizeof(buf)));
+
+ if (msg->ce_mask & QUEUE_MSG_ATTR_HOOK)
+ dp_dump(p, "HOOK=%s ",
+ nfnl_inet_hook2str(msg->queue_msg_hook,
+ buf, sizeof(buf)));
+
+ if (msg->ce_mask & QUEUE_MSG_ATTR_MARK)
+ dp_dump(p, "MARK=%d ", msg->queue_msg_mark);
+
+ if (msg->ce_mask & QUEUE_MSG_ATTR_PAYLOAD)
+ dp_dump(p, "PAYLOADLEN=%d ", msg->queue_msg_payload_len);
+
+ if (msg->ce_mask & QUEUE_MSG_ATTR_PACKETID)
+ dp_dump(p, "PACKETID=%u ", msg->queue_msg_packetid);
+
+ if (msg->ce_mask & QUEUE_MSG_ATTR_VERDICT)
+ dp_dump(p, "VERDICT=%s ",
+ nfnl_verdict2str(msg->queue_msg_verdict,
+ buf, sizeof(buf)));
+
+ dp_dump(p, "\n");
+
+ return 1;
+}
+
+/**
+ * @name Allocation/Freeing
+ * @{
+ */
+
+struct nfnl_queue_msg *nfnl_queue_msg_alloc(void)
+{
+ return (struct nfnl_queue_msg *) nl_object_alloc(&queue_msg_obj_ops);
+}
+
+void nfnl_queue_msg_get(struct nfnl_queue_msg *msg)
+{
+ nl_object_get((struct nl_object *) msg);
+}
+
+void nfnl_queue_msg_put(struct nfnl_queue_msg *msg)
+{
+ nl_object_put((struct nl_object *) msg);
+}
+
+/** @} */
+
+/**
+ * @name Attributes
+ * @{
+ */
+
+void nfnl_queue_msg_set_group(struct nfnl_queue_msg *msg, uint16_t group)
+{
+ msg->queue_msg_group = group;
+ msg->ce_mask |= QUEUE_MSG_ATTR_GROUP;
+}
+
+int nfnl_queue_msg_test_group(const struct nfnl_queue_msg *msg)
+{
+ return !!(msg->ce_mask & QUEUE_MSG_ATTR_GROUP);
+}
+
+uint16_t nfnl_queue_msg_get_group(const struct nfnl_queue_msg *msg)
+{
+ return msg->queue_msg_group;
+}
+
+void nfnl_queue_msg_set_family(struct nfnl_queue_msg *msg, uint8_t family)
+{
+ msg->queue_msg_family = family;
+ msg->ce_mask |= QUEUE_MSG_ATTR_FAMILY;
+}
+
+int nfnl_queue_msg_test_family(const struct nfnl_queue_msg *msg)
+{
+ return !!(msg->ce_mask & QUEUE_MSG_ATTR_FAMILY);
+}
+
+uint8_t nfnl_queue_msg_get_family(const struct nfnl_queue_msg *msg)
+{
+ if (msg->ce_mask & QUEUE_MSG_ATTR_FAMILY)
+ return msg->queue_msg_family;
+ else
+ return AF_UNSPEC;
+}
+
+void nfnl_queue_msg_set_packetid(struct nfnl_queue_msg *msg, uint32_t packetid)
+{
+ msg->queue_msg_packetid = packetid;
+ msg->ce_mask |= QUEUE_MSG_ATTR_PACKETID;
+}
+
+int nfnl_queue_msg_test_packetid(const struct nfnl_queue_msg *msg)
+{
+ return !!(msg->ce_mask & QUEUE_MSG_ATTR_PACKETID);
+}
+
+uint16_t nfnl_queue_msg_get_packetid(const struct nfnl_queue_msg *msg)
+{
+ return msg->queue_msg_packetid;
+}
+
+void nfnl_queue_msg_set_hwproto(struct nfnl_queue_msg *msg, uint16_t hwproto)
+{
+ msg->queue_msg_hwproto = hwproto;
+ msg->ce_mask |= QUEUE_MSG_ATTR_HWPROTO;
+}
+
+int nfnl_queue_msg_test_hwproto(const struct nfnl_queue_msg *msg)
+{
+ return !!(msg->ce_mask & QUEUE_MSG_ATTR_HWPROTO);
+}
+
+uint16_t nfnl_queue_msg_get_hwproto(const struct nfnl_queue_msg *msg)
+{
+ return msg->queue_msg_hwproto;
+}
+
+void nfnl_queue_msg_set_hook(struct nfnl_queue_msg *msg, uint8_t hook)
+{
+ msg->queue_msg_hook = hook;
+ msg->ce_mask |= QUEUE_MSG_ATTR_HOOK;
+}
+
+int nfnl_queue_msg_test_hook(const struct nfnl_queue_msg *msg)
+{
+ return !!(msg->ce_mask & QUEUE_MSG_ATTR_HOOK);
+}
+
+uint8_t nfnl_queue_msg_get_hook(const struct nfnl_queue_msg *msg)
+{
+ return msg->queue_msg_hook;
+}
+
+void nfnl_queue_msg_set_mark(struct nfnl_queue_msg *msg, uint32_t mark)
+{
+ msg->queue_msg_mark = mark;
+ msg->ce_mask |= QUEUE_MSG_ATTR_MARK;
+}
+
+int nfnl_queue_msg_test_mark(const struct nfnl_queue_msg *msg)
+{
+ return !!(msg->ce_mask & QUEUE_MSG_ATTR_MARK);
+}
+
+uint32_t nfnl_queue_msg_get_mark(const struct nfnl_queue_msg *msg)
+{
+ return msg->queue_msg_mark;
+}
+
+void nfnl_queue_msg_set_timestamp(struct nfnl_queue_msg *msg,
+ struct timeval *tv)
+{
+ msg->queue_msg_timestamp.tv_sec = tv->tv_sec;
+ msg->queue_msg_timestamp.tv_usec = tv->tv_usec;
+ msg->ce_mask |= QUEUE_MSG_ATTR_TIMESTAMP;
+}
+
+int nfnl_queue_msg_test_timestamp(const struct nfnl_queue_msg *msg)
+{
+ return !!(msg->ce_mask & QUEUE_MSG_ATTR_TIMESTAMP);
+}
+
+const struct timeval *nfnl_queue_msg_get_timestamp(const struct nfnl_queue_msg *msg)
+{
+ if (!(msg->ce_mask & QUEUE_MSG_ATTR_TIMESTAMP))
+ return NULL;
+ return &msg->queue_msg_timestamp;
+}
+
+void nfnl_queue_msg_set_indev(struct nfnl_queue_msg *msg, uint32_t indev)
+{
+ msg->queue_msg_indev = indev;
+ msg->ce_mask |= QUEUE_MSG_ATTR_INDEV;
+}
+
+int nfnl_queue_msg_test_indev(const struct nfnl_queue_msg *msg)
+{
+ return !!(msg->ce_mask & QUEUE_MSG_ATTR_INDEV);
+}
+
+uint32_t nfnl_queue_msg_get_indev(const struct nfnl_queue_msg *msg)
+{
+ return msg->queue_msg_indev;
+}
+
+void nfnl_queue_msg_set_outdev(struct nfnl_queue_msg *msg, uint32_t outdev)
+{
+ msg->queue_msg_outdev = outdev;
+ msg->ce_mask |= QUEUE_MSG_ATTR_OUTDEV;
+}
+
+int nfnl_queue_msg_test_outdev(const struct nfnl_queue_msg *msg)
+{
+ return !!(msg->ce_mask & QUEUE_MSG_ATTR_OUTDEV);
+}
+
+uint32_t nfnl_queue_msg_get_outdev(const struct nfnl_queue_msg *msg)
+{
+ return msg->queue_msg_outdev;
+}
+
+void nfnl_queue_msg_set_physindev(struct nfnl_queue_msg *msg,
+ uint32_t physindev)
+{
+ msg->queue_msg_physindev = physindev;
+ msg->ce_mask |= QUEUE_MSG_ATTR_PHYSINDEV;
+}
+
+int nfnl_queue_msg_test_physindev(const struct nfnl_queue_msg *msg)
+{
+ return !!(msg->ce_mask & QUEUE_MSG_ATTR_PHYSINDEV);
+}
+
+uint32_t nfnl_queue_msg_get_physindev(const struct nfnl_queue_msg *msg)
+{
+ return msg->queue_msg_physindev;
+}
+
+void nfnl_queue_msg_set_physoutdev(struct nfnl_queue_msg *msg,
+ uint32_t physoutdev)
+{
+ msg->queue_msg_physoutdev = physoutdev;
+ msg->ce_mask |= QUEUE_MSG_ATTR_PHYSOUTDEV;
+}
+
+int nfnl_queue_msg_test_physoutdev(const struct nfnl_queue_msg *msg)
+{
+ return !!(msg->ce_mask & QUEUE_MSG_ATTR_PHYSOUTDEV);
+}
+
+uint32_t nfnl_queue_msg_get_physoutdev(const struct nfnl_queue_msg *msg)
+{
+ return msg->queue_msg_physoutdev;
+}
+
+void nfnl_queue_msg_set_hwaddr(struct nfnl_queue_msg *msg, uint8_t *hwaddr,
+ int len)
+{
+ if (len > sizeof(msg->queue_msg_hwaddr))
+ len = sizeof(msg->queue_msg_hwaddr);
+
+ msg->queue_msg_hwaddr_len = len;
+ memcpy(msg->queue_msg_hwaddr, hwaddr, len);
+ msg->ce_mask |= QUEUE_MSG_ATTR_HWADDR;
+}
+
+int nfnl_queue_msg_test_hwaddr(const struct nfnl_queue_msg *msg)
+{
+ return !!(msg->ce_mask & QUEUE_MSG_ATTR_HWADDR);
+}
+
+const uint8_t *nfnl_queue_msg_get_hwaddr(const struct nfnl_queue_msg *msg,
+ int *len)
+{
+ if (!(msg->ce_mask & QUEUE_MSG_ATTR_HWADDR)) {
+ *len = 0;
+ return NULL;
+ }
+
+ *len = msg->queue_msg_hwaddr_len;
+ return msg->queue_msg_hwaddr;
+}
+
+int nfnl_queue_msg_set_payload(struct nfnl_queue_msg *msg, uint8_t *payload,
+ int len)
+{
+ free(msg->queue_msg_payload);
+ msg->queue_msg_payload = malloc(len);
+ if (!msg->queue_msg_payload)
+ return nl_errno(ENOMEM);
+
+ memcpy(msg->queue_msg_payload, payload, len);
+ msg->queue_msg_payload_len = len;
+ msg->ce_mask |= QUEUE_MSG_ATTR_PAYLOAD;
+ return 0;
+}
+
+int nfnl_queue_msg_test_payload(const struct nfnl_queue_msg *msg)
+{
+ return !!(msg->ce_mask & QUEUE_MSG_ATTR_PAYLOAD);
+}
+
+const void *nfnl_queue_msg_get_payload(const struct nfnl_queue_msg *msg, int *len)
+{
+ if (!(msg->ce_mask & QUEUE_MSG_ATTR_PAYLOAD)) {
+ *len = 0;
+ return NULL;
+ }
+
+ *len = msg->queue_msg_payload_len;
+ return msg->queue_msg_payload;
+}
+
+void nfnl_queue_msg_set_verdict(struct nfnl_queue_msg *msg,
+ unsigned int verdict)
+{
+ msg->queue_msg_verdict = verdict;
+ msg->ce_mask |= QUEUE_MSG_ATTR_VERDICT;
+}
+
+int nfnl_queue_msg_test_verdict(const struct nfnl_queue_msg *msg)
+{
+ return !!(msg->ce_mask & QUEUE_MSG_ATTR_VERDICT);
+}
+
+unsigned int nfnl_queue_msg_get_verdict(const struct nfnl_queue_msg *msg)
+{
+ return msg->queue_msg_verdict;
+}
+
+static struct trans_tbl nfnl_queue_msg_attrs[] = {
+ __ADD(QUEUE_MSG_ATTR_GROUP, group)
+ __ADD(QUEUE_MSG_ATTR_FAMILY, family)
+ __ADD(QUEUE_MSG_ATTR_PACKETID, packetid)
+ __ADD(QUEUE_MSG_ATTR_HWPROTO, hwproto)
+ __ADD(QUEUE_MSG_ATTR_HOOK, hook)
+ __ADD(QUEUE_MSG_ATTR_MARK, mark)
+ __ADD(QUEUE_MSG_ATTR_TIMESTAMP, timestamp)
+ __ADD(QUEUE_MSG_ATTR_INDEV, indev)
+ __ADD(QUEUE_MSG_ATTR_OUTDEV, outdev)
+ __ADD(QUEUE_MSG_ATTR_PHYSINDEV, physindev)
+ __ADD(QUEUE_MSG_ATTR_PHYSOUTDEV, physoutdev)
+ __ADD(QUEUE_MSG_ATTR_HWADDR, hwaddr)
+ __ADD(QUEUE_MSG_ATTR_PAYLOAD, payload)
+ __ADD(QUEUE_MSG_ATTR_VERDICT, verdict)
+};
+
+static char *nfnl_queue_msg_attrs2str(int attrs, char *buf, size_t len)
+{
+ return __flags2str(attrs, buf, len, nfnl_queue_msg_attrs,
+ ARRAY_SIZE(nfnl_queue_msg_attrs));
+}
+
+/** @} */
+
+struct nl_object_ops queue_msg_obj_ops = {
+ .oo_name = "netfilter/queuemsg",
+ .oo_size = sizeof(struct nfnl_queue_msg),
+ .oo_free_data = nfnl_queue_msg_free_data,
+ .oo_clone = nfnl_queue_msg_clone,
+ .oo_dump[NL_DUMP_BRIEF] = nfnl_queue_msg_dump,
+ .oo_dump[NL_DUMP_FULL] = nfnl_queue_msg_dump,
+ .oo_dump[NL_DUMP_STATS] = nfnl_queue_msg_dump,
+ .oo_attrs2str = nfnl_queue_msg_attrs2str,
+};
+
+/** @} */
diff --git a/lib/netfilter/queue_obj.c b/lib/netfilter/queue_obj.c
new file mode 100644
index 0000000..68e1e5a
--- /dev/null
+++ b/lib/netfilter/queue_obj.c
@@ -0,0 +1,213 @@
+/*
+ * lib/netfilter/queue_obj.c Netfilter Queue
+ *
+ * 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) 2007, 2008 Patrick McHardy <kaber@trash.net>
+ */
+
+/**
+ * @ingroup nfnl
+ * @defgroup queue Queue
+ * @brief
+ * @{
+ */
+
+#include <netlink-local.h>
+#include <netlink/netfilter/nfnl.h>
+#include <netlink/netfilter/queue.h>
+
+/** @cond SKIP */
+#define QUEUE_ATTR_GROUP (1UL << 0)
+#define QUEUE_ATTR_MAXLEN (1UL << 1)
+#define QUEUE_ATTR_COPY_MODE (1UL << 2)
+#define QUEUE_ATTR_COPY_RANGE (1UL << 3)
+/** @endcond */
+
+
+static int nfnl_queue_dump(struct nl_object *a, struct nl_dump_params *p)
+{
+ struct nfnl_queue *queue = (struct nfnl_queue *) a;
+ char buf[64];
+
+ if (queue->ce_mask & QUEUE_ATTR_GROUP)
+ dp_dump(p, "group=%u ", queue->queue_group);
+
+ if (queue->ce_mask & QUEUE_ATTR_MAXLEN)
+ dp_dump(p, "maxlen=%u ", queue->queue_maxlen);
+
+ if (queue->ce_mask & QUEUE_ATTR_COPY_MODE)
+ dp_dump(p, "copy_mode=%s ",
+ nfnl_queue_copy_mode2str(queue->queue_copy_mode,
+ buf, sizeof(buf)));
+
+ if (queue->ce_mask & QUEUE_ATTR_COPY_RANGE)
+ dp_dump(p, "copy_range=%u ", queue->queue_copy_range);
+
+ dp_dump(p, "\n");
+
+ return 1;
+}
+
+static struct trans_tbl copy_modes[] = {
+ __ADD(NFNL_QUEUE_COPY_NONE, none)
+ __ADD(NFNL_QUEUE_COPY_META, meta)
+ __ADD(NFNL_QUEUE_COPY_PACKET, packet)
+};
+
+char *nfnl_queue_copy_mode2str(enum nfnl_queue_copy_mode copy_mode, char *buf,
+ size_t len)
+{
+ return __type2str(copy_mode, buf, len, copy_modes,
+ ARRAY_SIZE(copy_modes));
+}
+
+enum nfnl_queue_copy_mode nfnl_queue_str2copy_mode(const char *name)
+{
+ return __str2type(name, copy_modes, ARRAY_SIZE(copy_modes));
+}
+
+/**
+ * @name Allocation/Freeing
+ * @{
+ */
+
+struct nfnl_queue *nfnl_queue_alloc(void)
+{
+ return (struct nfnl_queue *) nl_object_alloc(&queue_obj_ops);
+}
+
+void nfnl_queue_get(struct nfnl_queue *queue)
+{
+ nl_object_get((struct nl_object *) queue);
+}
+
+void nfnl_queue_put(struct nfnl_queue *queue)
+{
+ nl_object_put((struct nl_object *) queue);
+}
+
+/** @} */
+
+/**
+ * @name Attributes
+ * @{
+ */
+
+void nfnl_queue_set_group(struct nfnl_queue *queue, uint16_t group)
+{
+ queue->queue_group = group;
+ queue->ce_mask |= QUEUE_ATTR_GROUP;
+}
+
+int nfnl_queue_test_group(const struct nfnl_queue *queue)
+{
+ return !!(queue->ce_mask & QUEUE_ATTR_GROUP);
+}
+
+uint16_t nfnl_queue_get_group(const struct nfnl_queue *queue)
+{
+ return queue->queue_group;
+}
+
+void nfnl_queue_set_maxlen(struct nfnl_queue *queue, uint32_t maxlen)
+{
+ queue->queue_maxlen = maxlen;
+ queue->ce_mask |= QUEUE_ATTR_MAXLEN;
+}
+
+int nfnl_queue_test_maxlen(const struct nfnl_queue *queue)
+{
+ return !!(queue->ce_mask & QUEUE_ATTR_MAXLEN);
+}
+
+uint32_t nfnl_queue_get_maxlen(const struct nfnl_queue *queue)
+{
+ return queue->queue_maxlen;
+}
+
+void nfnl_queue_set_copy_mode(struct nfnl_queue *queue, enum nfnl_queue_copy_mode mode)
+{
+ queue->queue_copy_mode = mode;
+ queue->ce_mask |= QUEUE_ATTR_COPY_MODE;
+}
+
+int nfnl_queue_test_copy_mode(const struct nfnl_queue *queue)
+{
+ return !!(queue->ce_mask & QUEUE_ATTR_COPY_MODE);
+}
+
+enum nfnl_queue_copy_mode nfnl_queue_get_copy_mode(const struct nfnl_queue *queue)
+{
+ return queue->queue_copy_mode;
+}
+
+void nfnl_queue_set_copy_range(struct nfnl_queue *queue, uint32_t copy_range)
+{
+ queue->queue_copy_range = copy_range;
+ queue->ce_mask |= QUEUE_ATTR_COPY_RANGE;
+}
+
+int nfnl_queue_test_copy_range(const struct nfnl_queue *queue)
+{
+ return !!(queue->ce_mask & QUEUE_ATTR_COPY_RANGE);
+}
+
+uint32_t nfnl_queue_get_copy_range(const struct nfnl_queue *queue)
+{
+ return queue->queue_copy_range;
+}
+
+static int nfnl_queue_compare(struct nl_object *_a, struct nl_object *_b,
+ uint32_t attrs, int flags)
+{
+ struct nfnl_queue *a = (struct nfnl_queue *) _a;
+ struct nfnl_queue *b = (struct nfnl_queue *) _b;
+ int diff = 0;
+
+#define NFNL_QUEUE_DIFF(ATTR, EXPR) \
+ ATTR_DIFF(attrs, QUEUE_ATTR_##ATTR, a, b, EXPR)
+#define NFNL_QUEUE_DIFF_VAL(ATTR, FIELD) \
+ NFNL_QUEUE_DIFF(ATTR, a->FIELD != b->FIELD)
+
+ diff |= NFNL_QUEUE_DIFF_VAL(GROUP, queue_group);
+ diff |= NFNL_QUEUE_DIFF_VAL(MAXLEN, queue_maxlen);
+ diff |= NFNL_QUEUE_DIFF_VAL(COPY_MODE, queue_copy_mode);
+ diff |= NFNL_QUEUE_DIFF_VAL(COPY_RANGE, queue_copy_range);
+
+#undef NFNL_QUEUE_DIFF
+#undef NFNL_QUEUE_DIFF_VAL
+
+ return diff;
+}
+
+static struct trans_tbl nfnl_queue_attrs[] = {
+ __ADD(QUEUE_ATTR_GROUP, group)
+ __ADD(QUEUE_ATTR_MAXLEN, maxlen)
+ __ADD(QUEUE_ATTR_COPY_MODE, copy_mode)
+ __ADD(QUEUE_ATTR_COPY_RANGE, copy_range)
+};
+
+static char *nfnl_queue_attrs2str(int attrs, char *buf, size_t len)
+{
+ return __flags2str(attrs, buf, len, nfnl_queue_attrs,
+ ARRAY_SIZE(nfnl_queue_attrs));
+}
+
+/** @} */
+
+struct nl_object_ops queue_obj_ops = {
+ .oo_name = "netfilter/queue",
+ .oo_size = sizeof(struct nfnl_queue),
+ .oo_dump[NL_DUMP_BRIEF] = nfnl_queue_dump,
+ .oo_dump[NL_DUMP_FULL] = nfnl_queue_dump,
+ .oo_dump[NL_DUMP_STATS] = nfnl_queue_dump,
+ .oo_compare = nfnl_queue_compare,
+ .oo_attrs2str = nfnl_queue_attrs2str,
+ .oo_id_attrs = QUEUE_ATTR_GROUP,
+};
+
+/** @} */
diff --git a/src/nf-queue.c b/src/nf-queue.c
new file mode 100644
index 0000000..1420273
--- /dev/null
+++ b/src/nf-queue.c
@@ -0,0 +1,172 @@
+/*
+ * src/nf-log.c Monitor netfilter queue 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) 2007, 2008 Patrick McHardy <kaber@trash.net>
+ */
+
+#include <sys/types.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/nfnetlink_queue.h>
+
+#include "utils.h"
+#include <netlink/netfilter/nfnl.h>
+#include <netlink/netfilter/queue.h>
+#include <netlink/netfilter/queue_msg.h>
+
+static struct nl_handle *nfnlh;
+
+static void obj_input(struct nl_object *obj, void *arg)
+{
+ struct nfnl_queue_msg *msg = (struct nfnl_queue_msg *) obj;
+ struct nl_dump_params dp = {
+ .dp_type = NL_DUMP_STATS,
+ .dp_fd = stdout,
+ .dp_dump_msgtype = 1,
+ };
+
+ nfnl_queue_msg_set_verdict(msg, NF_ACCEPT);
+ nl_object_dump(obj, &dp);
+ nfnl_queue_msg_send_verdict(nfnlh, msg);
+}
+
+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_STOP;
+}
+
+int main(int argc, char *argv[])
+{
+ struct nl_handle *rtnlh;
+ struct nl_cache *link_cache;
+ struct nfnl_queue *queue;
+ enum nfnl_queue_copy_mode copy_mode;
+ uint32_t copy_range;
+ int err = 1;
+ int family;
+
+ 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-queue family group [ copy_mode ] "
+ "[ copy_range ]\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;
+ }
+
+ nfnl_queue_pf_unbind(nfnlh, family);
+ if (nfnl_queue_pf_bind(nfnlh, family) < 0) {
+ fprintf(stderr, "%s\n", nl_geterror());
+ goto errout;
+ }
+
+ queue = nfnl_queue_alloc();
+ if (queue == NULL) {
+ fprintf(stderr, "%s\n", nl_geterror());
+ goto errout;
+ }
+
+ nfnl_queue_set_group(queue, atoi(argv[2]));
+
+ copy_mode = NFNL_QUEUE_COPY_PACKET;
+ if (argc > 3) {
+ copy_mode = nfnl_queue_str2copy_mode(argv[3]);
+ if (copy_mode < 0) {
+ fprintf(stderr, "%s\n", nl_geterror());
+ goto errout;
+ }
+ }
+ nfnl_queue_set_copy_mode(queue, copy_mode);
+
+ copy_range = 0xFFFF;
+ if (argc > 4)
+ copy_range = atoi(argv[4]);
+ nfnl_queue_set_copy_range(queue, copy_range);
+
+ if (nfnl_queue_create(nfnlh, queue) < 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_default(nfnlh);
+ if (FD_ISSET(rtfd, &rfds))
+ nl_recvmsgs_default(rtnlh);
+ }
+ }
+
+ nl_cache_mngt_unprovide(link_cache);
+ nl_cache_free(link_cache);
+
+ nfnl_queue_put(queue);
+
+ nl_close(rtnlh);
+ nl_handle_destroy(rtnlh);
+errout_close:
+ nl_close(nfnlh);
+ nl_handle_destroy(nfnlh);
+errout:
+ return err;
+}
^ permalink raw reply related [flat|nested] 26+ messages in thread* [LIBNL 05/09]: nfnetlink_log: only set hwproto if not zero
2008-01-18 16:55 [LIBNL 00/09]: Netfilter update + minor fixes Patrick McHardy
` (3 preceding siblings ...)
2008-01-18 16:55 ` [LIBNL 04/09]: Add nfnetlink_queue support Patrick McHardy
@ 2008-01-18 16:55 ` Patrick McHardy
2008-02-07 12:01 ` Thomas Graf
2008-01-18 16:55 ` [LIBNL 06/09]: nfnetlink_log: support NUFLA_GID attribute Patrick McHardy
` (3 subsequent siblings)
8 siblings, 1 reply; 26+ messages in thread
From: Patrick McHardy @ 2008-01-18 16:55 UTC (permalink / raw)
To: tgraf; +Cc: Patrick McHardy, netfilter-devel, philipc
commit 26b35449524246778d4a14c3805430797c29c039
Author: Patrick McHardy <kaber@trash.net>
Date: Fri Jan 18 17:44:52 2008 +0100
[LIBNL]: nfnetlink_log: only set hwproto if not zero
The hwproto doesn't have its own attribute and is also present when
not set. Don't set the attribute if its value is zero.
Signed-off-by: Patrick McHardy <kaber@trash.net>
diff --git a/lib/netfilter/log.c b/lib/netfilter/log.c
index a6bf3d5..a900927 100644
--- a/lib/netfilter/log.c
+++ b/lib/netfilter/log.c
@@ -86,7 +86,8 @@ struct nfnl_log *nfnlmsg_log_parse(struct nlmsghdr *nlh)
if (attr) {
struct nfulnl_msg_packet_hdr *hdr = nla_data(attr);
- nfnl_log_set_hwproto(log, hdr->hw_protocol);
+ if (hdr->hw_protocol)
+ nfnl_log_set_hwproto(log, hdr->hw_protocol);
nfnl_log_set_hook(log, hdr->hook);
}
^ permalink raw reply related [flat|nested] 26+ messages in thread* [LIBNL 06/09]: nfnetlink_log: support NUFLA_GID attribute
2008-01-18 16:55 [LIBNL 00/09]: Netfilter update + minor fixes Patrick McHardy
` (4 preceding siblings ...)
2008-01-18 16:55 ` [LIBNL 05/09]: nfnetlink_log: only set hwproto if not zero Patrick McHardy
@ 2008-01-18 16:55 ` Patrick McHardy
2008-02-07 12:03 ` Thomas Graf
2008-01-18 16:55 ` [LIBNL 07/09]: Split up nfnetlink_log into log and msg objects Patrick McHardy
` (2 subsequent siblings)
8 siblings, 1 reply; 26+ messages in thread
From: Patrick McHardy @ 2008-01-18 16:55 UTC (permalink / raw)
To: tgraf; +Cc: Patrick McHardy, netfilter-devel, philipc
commit 2c2e8051726fb34980d1e7b72c15d0a6eba4cfc0
Author: Patrick McHardy <kaber@trash.net>
Date: Fri Jan 18 17:44:52 2008 +0100
[LIBNL]: nfnetlink_log: support NUFLA_GID attribute
The NUFLA_GID attribute (currently only in net-2.6.25) contains the
gid of the sending process for locally generated packets.
Signed-off-by: Patrick McHardy <kaber@trash.net>
diff --git a/include/linux/netfilter/nfnetlink_log.h b/include/linux/netfilter/nfnetlink_log.h
index 2de5df9..38fafc1 100644
--- a/include/linux/netfilter/nfnetlink_log.h
+++ b/include/linux/netfilter/nfnetlink_log.h
@@ -51,6 +51,7 @@ enum nfulnl_attr_type {
NFULA_UID, /* user id of socket */
NFULA_SEQ, /* instance-local sequence number */
NFULA_SEQ_GLOBAL, /* global sequence number */
+ NFULA_GID, /* group id of socket */
__NFULA_MAX
};
diff --git a/include/netlink-types.h b/include/netlink-types.h
index f7bddca..cbf903e 100644
--- a/include/netlink-types.h
+++ b/include/netlink-types.h
@@ -751,6 +751,7 @@ struct nfnl_log {
int log_payload_len;
char * log_prefix;
uint32_t log_uid;
+ uint32_t log_gid;
uint32_t log_seq;
uint32_t log_seq_global;
};
diff --git a/include/netlink/netfilter/log.h b/include/netlink/netfilter/log.h
index e65cc58..817de2d 100644
--- a/include/netlink/netfilter/log.h
+++ b/include/netlink/netfilter/log.h
@@ -89,6 +89,10 @@ 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_gid(struct nfnl_log *, uint32_t);
+extern int nfnl_log_test_gid(const struct nfnl_log *);
+extern uint32_t nfnl_log_get_gid(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 *);
diff --git a/lib/netfilter/log.c b/lib/netfilter/log.c
index a900927..8d70e7f 100644
--- a/lib/netfilter/log.c
+++ b/lib/netfilter/log.c
@@ -58,6 +58,7 @@ static struct nla_policy log_policy[NFULA_MAX+1] = {
//[NFULA_PAYLOAD]
[NFULA_PREFIX] = { .type = NLA_STRING, },
[NFULA_UID] = { .type = NLA_U32 },
+ [NFULA_GID] = { .type = NLA_U32 },
[NFULA_SEQ] = { .type = NLA_U32 },
[NFULA_SEQ_GLOBAL] = { .type = NLA_U32 },
};
@@ -146,6 +147,10 @@ struct nfnl_log *nfnlmsg_log_parse(struct nlmsghdr *nlh)
if (attr)
nfnl_log_set_uid(log, ntohl(nla_get_u32(attr)));
+ attr = tb[NFULA_GID];
+ if (attr)
+ nfnl_log_set_gid(log, ntohl(nla_get_u32(attr)));
+
attr = tb[NFULA_SEQ];
if (attr)
nfnl_log_set_seq(log, ntohl(nla_get_u32(attr)));
diff --git a/lib/netfilter/log_obj.c b/lib/netfilter/log_obj.c
index c3adc51..0e4411e 100644
--- a/lib/netfilter/log_obj.c
+++ b/lib/netfilter/log_obj.c
@@ -29,8 +29,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)
+#define LOG_ATTR_GID (1UL << 13)
+#define LOG_ATTR_SEQ (1UL << 14)
+#define LOG_ATTR_SEQ_GLOBAL (1UL << 15)
/** @endcond */
static void log_free_data(struct nl_object *c)
@@ -144,6 +145,12 @@ static int log_dump(struct nl_object *a, struct nl_dump_params *p)
if (log->ce_mask & LOG_ATTR_PAYLOAD)
dp_dump(p, "PAYLOADLEN=%d ", log->log_payload_len);
+ if (log->ce_mask & LOG_ATTR_UID)
+ dp_dump(p, "UID=%u ", log->log_uid);
+
+ if (log->ce_mask & LOG_ATTR_GID)
+ dp_dump(p, "GID=%u ", log->log_gid);
+
if (log->ce_mask & LOG_ATTR_SEQ)
dp_dump(p, "SEQ=%d ", log->log_seq);
@@ -378,6 +385,23 @@ uint32_t nfnl_log_get_uid(const struct nfnl_log *log)
return log->log_uid;
}
+void nfnl_log_set_gid(struct nfnl_log *log, uint32_t gid)
+{
+ log->log_gid = gid;
+ log->ce_mask |= LOG_ATTR_GID;
+}
+
+int nfnl_log_test_gid(const struct nfnl_log *log)
+{
+ return !!(log->ce_mask & LOG_ATTR_GID);
+}
+
+uint32_t nfnl_log_get_gid(const struct nfnl_log *log)
+{
+ return log->log_gid;
+}
+
+
void nfnl_log_set_seq(struct nfnl_log *log, uint32_t seq)
{
log->log_seq = seq;
^ permalink raw reply related [flat|nested] 26+ messages in thread* [LIBNL 07/09]: Split up nfnetlink_log into log and msg objects
2008-01-18 16:55 [LIBNL 00/09]: Netfilter update + minor fixes Patrick McHardy
` (5 preceding siblings ...)
2008-01-18 16:55 ` [LIBNL 06/09]: nfnetlink_log: support NUFLA_GID attribute Patrick McHardy
@ 2008-01-18 16:55 ` Patrick McHardy
2008-01-21 8:05 ` Philip Craig
2008-02-07 12:11 ` Thomas Graf
2008-01-18 16:55 ` [LIBNL 08/09]: Support conntrack add/delete/query requests Patrick McHardy
2008-01-18 16:56 ` [LIBNL 09/09]: Install netfilter headers Patrick McHardy
8 siblings, 2 replies; 26+ messages in thread
From: Patrick McHardy @ 2008-01-18 16:55 UTC (permalink / raw)
To: tgraf; +Cc: Patrick McHardy, netfilter-devel, philipc
commit c566db4405200994482d36fac45089aba4e2360a
Author: Patrick McHardy <kaber@trash.net>
Date: Fri Jan 18 17:52:41 2008 +0100
[LIBNL]: Split up nfnetlink_log into log and msg objects
Split the nfnetlink_log code into two seperate objects, "netfilter/log"
to represent logging instances and "netfilter/log_msg" to represent
log messages. Also perform some function name unification for consistency
with other libnl object types, mainly renaming nfnl_log_build_*_msg
to nfnl_log_build_*_request.
This changes the API in an incompatible way, but since this feature is
new and the libnl netfilter headers haven't been installed so far,
there shouldn't be any users affected by this.
Signed-off-by: Patrick McHardy <kaber@trash.net>
diff --git a/include/netlink-types.h b/include/netlink-types.h
index cbf903e..a690cb2 100644
--- a/include/netlink-types.h
+++ b/include/netlink-types.h
@@ -736,24 +736,37 @@ struct nfnl_ct {
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_gid;
- uint32_t log_seq;
- uint32_t log_seq_global;
+ uint16_t log_group;
+ uint8_t log_copy_mode;
+ uint32_t log_copy_range;
+ uint32_t log_flush_timeout;
+ uint32_t log_alloc_size;
+ uint32_t log_queue_threshold;
+ uint32_t log_flags;
+ uint32_t log_flag_mask;
+};
+
+struct nfnl_log_msg {
+ NLHDR_COMMON
+
+ uint8_t log_msg_family;
+ uint8_t log_msg_hook;
+ uint16_t log_msg_hwproto;
+ uint32_t log_msg_mark;
+ struct timeval log_msg_timestamp;
+ uint32_t log_msg_indev;
+ uint32_t log_msg_outdev;
+ uint32_t log_msg_physindev;
+ uint32_t log_msg_physoutdev;
+ uint8_t log_msg_hwaddr[8];
+ int log_msg_hwaddr_len;
+ void * log_msg_payload;
+ int log_msg_payload_len;
+ char * log_msg_prefix;
+ uint32_t log_msg_uid;
+ uint32_t log_msg_gid;
+ uint32_t log_msg_seq;
+ uint32_t log_msg_seq_global;
};
struct nfnl_queue {
diff --git a/include/netlink/netfilter/log.h b/include/netlink/netfilter/log.h
index 817de2d..51f4a90 100644
--- a/include/netlink/netfilter/log.h
+++ b/include/netlink/netfilter/log.h
@@ -9,6 +9,7 @@
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
* Copyright (c) 2007 Philip Craig <philipc@snapgear.com>
* Copyright (c) 2007 Secure Computing Corporation
+ * Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
*/
#ifndef NETLINK_LOG_H_
@@ -26,80 +27,79 @@ 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 *);
+enum nfnl_log_copy_mode {
+ NFNL_LOG_COPY_NONE,
+ NFNL_LOG_COPY_META,
+ NFNL_LOG_COPY_PACKET,
+};
-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);
+enum nfnl_log_flags {
+ NFNL_LOG_FLAG_SEQ = 0x1,
+ NFNL_LOG_FLAG_SEQ_GLOBAL = 0x2,
+};
-extern void nfnl_log_set_family(struct nfnl_log *, uint8_t);
-extern uint8_t nfnl_log_get_family(const struct nfnl_log *);
+/* General */
+extern struct nfnl_log * nfnl_log_alloc(void);
+extern struct nfnl_log * nfnlmsg_log_parse(struct nlmsghdr *);
-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_get(struct nfnl_log *);
+extern void nfnl_log_put(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 *);
+/* Attributes */
+extern void nfnl_log_set_group(struct nfnl_log *, uint16_t);
+extern int nfnl_log_test_group(const struct nfnl_log *);
+extern uint16_t nfnl_log_get_group(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_copy_mode(struct nfnl_log *,
+ enum nfnl_log_copy_mode);
+extern int nfnl_log_test_copy_mode(const struct nfnl_log *);
+extern enum nfnl_log_copy_mode nfnl_log_get_copy_mode(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 char * nfnl_log_copy_mode2str(enum nfnl_log_copy_mode,
+ char *, size_t);
+extern enum nfnl_log_copy_mode nfnl_log_str2copy_mode(const char *);
-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_copy_range(struct nfnl_log *, uint32_t);
+extern int nfnl_log_test_copy_range(const struct nfnl_log *);
+extern uint32_t nfnl_log_get_copy_range(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_flush_timeout(struct nfnl_log *, uint32_t);
+extern int nfnl_log_test_flush_timeout(const struct nfnl_log *);
+extern uint32_t nfnl_log_get_flush_timeout(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_alloc_size(struct nfnl_log *, uint32_t);
+extern int nfnl_log_test_alloc_size(const struct nfnl_log *);
+extern uint32_t nfnl_log_get_alloc_size(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_queue_threshold(struct nfnl_log *, uint32_t);
+extern int nfnl_log_test_queue_threshold(const struct nfnl_log *);
+extern uint32_t nfnl_log_get_queue_threshold(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 void nfnl_log_set_flags(struct nfnl_log *, unsigned int);
+extern void nfnl_log_unset_flags(struct nfnl_log *, unsigned int);
+extern unsigned int nfnl_log_get_flags(const struct nfnl_log *);
-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 char * nfnl_log_flags2str(unsigned int, char *, size_t);
+extern unsigned int nfnl_log_str2flags(const char *);
-extern int nfnl_log_set_prefix(struct nfnl_log *, void *);
-extern const char * nfnl_log_get_prefix(const struct nfnl_log *);
+/* Message construction / sending */
+extern struct nl_msg * nfnl_log_build_pf_bind(uint8_t);
+extern int nfnl_log_pf_bind(struct nl_handle *, uint8_t);
-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 struct nl_msg * nfnl_log_build_pf_unbind(uint8_t);
+extern int nfnl_log_pf_unbind(struct nl_handle *, uint8_t);
-extern void nfnl_log_set_gid(struct nfnl_log *, uint32_t);
-extern int nfnl_log_test_gid(const struct nfnl_log *);
-extern uint32_t nfnl_log_get_gid(const struct nfnl_log *);
+extern struct nl_msg * nfnl_log_build_create_request(const struct nfnl_log *);
+extern int nfnl_log_create(struct nl_handle *,
+ 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 struct nl_msg * nfnl_log_build_change_request(const struct nfnl_log *);
+extern int nfnl_log_change(struct nl_handle *,
+ 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 *);
+extern struct nl_msg * nfnl_log_build_delete_request(const struct nfnl_log *);
+extern int nfnl_log_delete(struct nl_handle *,
+ const struct nfnl_log *);
#ifdef __cplusplus
}
diff --git a/include/netlink/netfilter/log_msg.h b/include/netlink/netfilter/log_msg.h
new file mode 100644
index 0000000..0cdb6c6
--- /dev/null
+++ b/include/netlink/netfilter/log_msg.h
@@ -0,0 +1,98 @@
+/*
+ * netlink/netfilter/log_msg.h Netfilter Log Message
+ *
+ * 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
+ * Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
+ */
+
+#ifndef NETLINK_LOG_MSG_H_
+#define NETLINK_LOG_MSG_H_
+
+#include <netlink/netlink.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct nl_handle;
+struct nlmsghdr;
+struct nfnl_log_msg;
+
+extern struct nl_object_ops log_msg_obj_ops;
+
+/* General */
+extern struct nfnl_log_msg *nfnl_log_msg_alloc(void);
+extern struct nfnl_log_msg *nfnlmsg_log_msg_parse(struct nlmsghdr *);
+
+extern void nfnl_log_msg_get(struct nfnl_log_msg *);
+extern void nfnl_log_msg_put(struct nfnl_log_msg *);
+
+extern void nfnl_log_msg_set_family(struct nfnl_log_msg *, uint8_t);
+extern uint8_t nfnl_log_msg_get_family(const struct nfnl_log_msg *);
+
+extern void nfnl_log_msg_set_hwproto(struct nfnl_log_msg *, uint16_t);
+extern int nfnl_log_msg_test_hwproto(const struct nfnl_log_msg *);
+extern uint16_t nfnl_log_msg_get_hwproto(const struct nfnl_log_msg *);
+
+extern void nfnl_log_msg_set_hook(struct nfnl_log_msg *, uint8_t);
+extern int nfnl_log_msg_test_hook(const struct nfnl_log_msg *);
+extern uint8_t nfnl_log_msg_get_hook(const struct nfnl_log_msg *);
+
+extern void nfnl_log_msg_set_mark(struct nfnl_log_msg *, uint32_t);
+extern int nfnl_log_msg_test_mark(const struct nfnl_log_msg *);
+extern uint32_t nfnl_log_msg_get_mark(const struct nfnl_log_msg *);
+
+extern void nfnl_log_msg_set_timestamp(struct nfnl_log_msg *,
+ struct timeval *);
+extern const struct timeval *nfnl_log_msg_get_timestamp(const struct nfnl_log_msg *);
+
+extern void nfnl_log_msg_set_indev(struct nfnl_log_msg *, uint32_t);
+extern uint32_t nfnl_log_msg_get_indev(const struct nfnl_log_msg *);
+
+extern void nfnl_log_msg_set_outdev(struct nfnl_log_msg *, uint32_t);
+extern uint32_t nfnl_log_msg_get_outdev(const struct nfnl_log_msg *);
+
+extern void nfnl_log_msg_set_physindev(struct nfnl_log_msg *, uint32_t);
+extern uint32_t nfnl_log_msg_get_physindev(const struct nfnl_log_msg *);
+
+extern void nfnl_log_msg_set_physoutdev(struct nfnl_log_msg *, uint32_t);
+extern uint32_t nfnl_log_msg_get_physoutdev(const struct nfnl_log_msg *);
+
+extern void nfnl_log_msg_set_hwaddr(struct nfnl_log_msg *, uint8_t *, int);
+extern const uint8_t * nfnl_log_msg_get_hwaddr(const struct nfnl_log_msg *, int *);
+
+extern int nfnl_log_msg_set_payload(struct nfnl_log_msg *, uint8_t *, int);
+extern const void * nfnl_log_msg_get_payload(const struct nfnl_log_msg *, int *);
+
+extern int nfnl_log_msg_set_prefix(struct nfnl_log_msg *, void *);
+extern const char * nfnl_log_msg_get_prefix(const struct nfnl_log_msg *);
+
+extern void nfnl_log_msg_set_uid(struct nfnl_log_msg *, uint32_t);
+extern int nfnl_log_msg_test_uid(const struct nfnl_log_msg *);
+extern uint32_t nfnl_log_msg_get_uid(const struct nfnl_log_msg *);
+
+extern void nfnl_log_msg_set_gid(struct nfnl_log_msg *, uint32_t);
+extern int nfnl_log_msg_test_gid(const struct nfnl_log_msg *);
+extern uint32_t nfnl_log_msg_get_gid(const struct nfnl_log_msg *);
+
+extern void nfnl_log_msg_set_seq(struct nfnl_log_msg *, uint32_t);
+extern int nfnl_log_msg_test_seq(const struct nfnl_log_msg *);
+extern uint32_t nfnl_log_msg_get_seq(const struct nfnl_log_msg *);
+
+extern void nfnl_log_msg_set_seq_global(struct nfnl_log_msg *, uint32_t);
+extern int nfnl_log_msg_test_seq_global(const struct nfnl_log_msg *);
+extern uint32_t nfnl_log_msg_get_seq_global(const struct nfnl_log_msg *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/lib/netfilter/log.c b/lib/netfilter/log.c
index 8d70e7f..c92d401 100644
--- a/lib/netfilter/log.c
+++ b/lib/netfilter/log.c
@@ -26,178 +26,13 @@
#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_GID] = { .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);
-
- if (hdr->hw_protocol)
- 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_GID];
- if (attr)
- nfnl_log_set_gid(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, struct nl_parser_param *pp)
-{
- 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;
-
- err = P_ACCEPT;
-
-errout:
- nfnl_log_put(log);
- return err;
-
-errout_errno:
- err = nl_get_errno();
- goto errout;
-}
-
/**
* @name Log Commands
* @{
*/
-static struct nl_msg *build_log_cmd_msg(uint8_t family, uint16_t queuenum,
- uint8_t command)
+static struct nl_msg *build_log_cmd_request(uint8_t family, uint16_t queuenum,
+ uint8_t command)
{
struct nl_msg *msg;
struct nfulnl_msg_config_cmd cmd;
@@ -218,7 +53,7 @@ nla_put_failure:
return NULL;
}
-static int send_log_msg(struct nl_handle *handle, struct nl_msg *msg)
+static int send_log_request(struct nl_handle *handle, struct nl_msg *msg)
{
int err;
@@ -230,84 +65,108 @@ static int send_log_msg(struct nl_handle *handle, struct nl_msg *msg)
return nl_wait_for_ack(handle);
}
-struct nl_msg *nfnl_log_build_bind(uint16_t queuenum)
+struct nl_msg *nfnl_log_build_pf_bind(uint8_t pf)
{
- return build_log_cmd_msg(0, queuenum, NFULNL_CFG_CMD_BIND);
+ return build_log_cmd_request(pf, 0, NFULNL_CFG_CMD_PF_BIND);
}
-int nfnl_log_bind(struct nl_handle *nlh, uint16_t queuenum)
+int nfnl_log_pf_bind(struct nl_handle *nlh, uint8_t pf)
{
struct nl_msg *msg;
- msg = nfnl_log_build_bind(queuenum);
+ msg = nfnl_log_build_pf_bind(pf);
if (!msg)
return nl_get_errno();
- return send_log_msg(nlh, msg);
+ return send_log_request(nlh, msg);
}
-struct nl_msg *nfnl_log_build_unbind(uint16_t queuenum)
+struct nl_msg *nfnl_log_build_pf_unbind(uint8_t pf)
{
- return build_log_cmd_msg(0, queuenum, NFULNL_CFG_CMD_UNBIND);
+ return build_log_cmd_request(pf, 0, NFULNL_CFG_CMD_PF_UNBIND);
}
-int nfnl_log_unbind(struct nl_handle *nlh, uint16_t queuenum)
+int nfnl_log_pf_unbind(struct nl_handle *nlh, uint8_t pf)
{
struct nl_msg *msg;
- msg = nfnl_log_build_bind(queuenum);
+ 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_pf_bind(uint8_t pf)
-{
- return build_log_cmd_msg(pf, 0, NFULNL_CFG_CMD_PF_BIND);
+ return send_log_request(nlh, msg);
}
-int nfnl_log_pf_bind(struct nl_handle *nlh, uint8_t pf)
+static struct nl_msg *nfnl_log_build_request(const struct nfnl_log *log)
{
struct nl_msg *msg;
- msg = nfnl_log_build_pf_bind(pf);
- if (!msg)
- return nl_get_errno();
+ if (!nfnl_log_test_group(log))
+ return NULL;
- return send_log_msg(nlh, msg);
-}
+ msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_ULOG, NFULNL_MSG_CONFIG, 0,
+ 0, nfnl_log_get_group(log));
+ if (msg == NULL)
+ return NULL;
-struct nl_msg *nfnl_log_build_pf_unbind(uint8_t pf)
-{
- return build_log_cmd_msg(pf, 0, NFULNL_CFG_CMD_PF_UNBIND);
-}
+ /* This sucks. The nfnetlink_log interface always expects both
+ * parameters to be present. Needs to be done properly.
+ */
+ if (nfnl_log_test_copy_mode(log)) {
+ struct nfulnl_msg_config_mode mode;
+
+ switch (nfnl_log_get_copy_mode(log)) {
+ case NFNL_LOG_COPY_NONE:
+ mode.copy_mode = NFULNL_COPY_NONE;
+ break;
+ case NFNL_LOG_COPY_META:
+ mode.copy_mode = NFULNL_COPY_META;
+ break;
+ case NFNL_LOG_COPY_PACKET:
+ mode.copy_mode = NFULNL_COPY_PACKET;
+ break;
+ }
+ mode.copy_range = htonl(nfnl_log_get_copy_range(log));
+ mode._pad = 0;
+
+ if (nla_put(msg, NFULA_CFG_MODE, sizeof(mode), &mode) < 0)
+ goto nla_put_failure;
+ }
-int nfnl_log_pf_unbind(struct nl_handle *nlh, uint8_t pf)
-{
- struct nl_msg *msg;
+ if (nfnl_log_test_flush_timeout(log) &&
+ nla_put_u32(msg, NFULA_CFG_TIMEOUT,
+ htonl(nfnl_log_get_flush_timeout(log))) < 0)
+ goto nla_put_failure;
- msg = nfnl_log_build_pf_unbind(pf);
- if (!msg)
- return nl_get_errno();
+ if (nfnl_log_test_alloc_size(log) &&
+ nla_put_u32(msg, NFULA_CFG_NLBUFSIZ,
+ htonl(nfnl_log_get_alloc_size(log))) < 0)
+ goto nla_put_failure;
- return send_log_msg(nlh, msg);
+ if (nfnl_log_test_queue_threshold(log) &&
+ nla_put_u32(msg, NFULA_CFG_QTHRESH,
+ htonl(nfnl_log_get_queue_threshold(log))) < 0)
+ goto nla_put_failure;
+
+ return msg;
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return NULL;
}
-struct nl_msg *nfnl_log_build_mode(uint16_t queuenum, uint8_t copy_mode,
- uint32_t copy_range)
+struct nl_msg *nfnl_log_build_create_request(const struct nfnl_log *log)
{
struct nl_msg *msg;
- struct nfulnl_msg_config_mode mode;
+ struct nfulnl_msg_config_cmd cmd;
- msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_ULOG, NFULNL_MSG_CONFIG, 0,
- 0, queuenum);
+ msg = nfnl_log_build_request(log);
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)
+ cmd.command = NFULNL_CFG_CMD_BIND;
+
+ if (nla_put(msg, NFULA_CFG_CMD, sizeof(cmd), &cmd) < 0)
goto nla_put_failure;
return msg;
@@ -317,29 +176,57 @@ nla_put_failure:
return NULL;
}
-int nfnl_log_set_mode(struct nl_handle *nlh, uint16_t queuenum,
- uint8_t copy_mode, uint32_t copy_range)
+int nfnl_log_create(struct nl_handle *nlh, const struct nfnl_log *log)
{
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);
+ msg = nfnl_log_build_create_request(log);
+ if (msg == NULL)
+ return nl_errno(ENOMEM);
+
+ return send_log_request(nlh, msg);
+}
+
+struct nl_msg *nfnl_log_build_change_request(const struct nfnl_log *log)
+{
+ return nfnl_log_build_request(log);
+}
+
+int nfnl_log_change(struct nl_handle *nlh, const struct nfnl_log *log)
+{
+ struct nl_msg *msg;
+
+ msg = nfnl_log_build_change_request(log);
+ if (msg == NULL)
+ return nl_errno(ENOMEM);
+
+ return send_log_request(nlh, msg);
+}
+
+struct nl_msg *nfnl_log_build_delete_request(const struct nfnl_log *log)
+{
+ if (!nfnl_log_test_group(log))
+ return NULL;
+
+ return build_log_cmd_request(0, nfnl_log_get_group(log),
+ NFULNL_CFG_CMD_UNBIND);
+}
+
+int nfnl_log_delete(struct nl_handle *nlh, const struct nfnl_log *log)
+{
+ struct nl_msg *msg;
+
+ msg = nfnl_log_build_delete_request(log);
+ if (msg == NULL)
+ return nl_errno(ENOMEM);
+
+ return send_log_request(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,
};
diff --git a/lib/netfilter/log_msg.c b/lib/netfilter/log_msg.c
new file mode 100644
index 0000000..5243338
--- /dev/null
+++ b/lib/netfilter/log_msg.c
@@ -0,0 +1,218 @@
+/*
+ * lib/netfilter/log_msg.c Netfilter Log Message
+ *
+ * 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
+ * Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
+ */
+
+/**
+ * @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_msg.h>
+
+#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_msg_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_GID] = { .type = NLA_U32 },
+ [NFULA_SEQ] = { .type = NLA_U32 },
+ [NFULA_SEQ_GLOBAL] = { .type = NLA_U32 },
+};
+
+struct nfnl_log_msg *nfnlmsg_log_msg_parse(struct nlmsghdr *nlh)
+{
+ struct nfnl_log_msg *msg;
+ struct nlattr *tb[NFULA_MAX+1];
+ struct nlattr *attr;
+ int err;
+
+ msg = nfnl_log_msg_alloc();
+ if (!msg)
+ return NULL;
+
+ msg->ce_msgtype = nlh->nlmsg_type;
+
+ err = nlmsg_parse(nlh, sizeof(struct nfgenmsg), tb, NFULA_MAX,
+ log_msg_policy);
+ if (err < 0)
+ goto errout;
+
+ nfnl_log_msg_set_family(msg, nfnlmsg_family(nlh));
+
+ attr = tb[NFULA_PACKET_HDR];
+ if (attr) {
+ struct nfulnl_msg_packet_hdr *hdr = nla_data(attr);
+
+ if (hdr->hw_protocol)
+ nfnl_log_msg_set_hwproto(msg, hdr->hw_protocol);
+ nfnl_log_msg_set_hook(msg, hdr->hook);
+ }
+
+ attr = tb[NFULA_MARK];
+ if (attr)
+ nfnl_log_msg_set_mark(msg, 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_msg_set_timestamp(msg, &tv);
+ }
+
+ attr = tb[NFULA_IFINDEX_INDEV];
+ if (attr)
+ nfnl_log_msg_set_indev(msg, ntohl(nla_get_u32(attr)));
+
+ attr = tb[NFULA_IFINDEX_OUTDEV];
+ if (attr)
+ nfnl_log_msg_set_outdev(msg, ntohl(nla_get_u32(attr)));
+
+ attr = tb[NFULA_IFINDEX_PHYSINDEV];
+ if (attr)
+ nfnl_log_msg_set_physindev(msg, ntohl(nla_get_u32(attr)));
+
+ attr = tb[NFULA_IFINDEX_PHYSOUTDEV];
+ if (attr)
+ nfnl_log_msg_set_physoutdev(msg, ntohl(nla_get_u32(attr)));
+
+ attr = tb[NFULA_HWADDR];
+ if (attr) {
+ struct nfulnl_msg_packet_hw *hw = nla_data(attr);
+
+ nfnl_log_msg_set_hwaddr(msg, hw->hw_addr, ntohs(hw->hw_addrlen));
+ }
+
+ attr = tb[NFULA_PAYLOAD];
+ if (attr) {
+ err = nfnl_log_msg_set_payload(msg, nla_data(attr), nla_len(attr));
+ if (err < 0)
+ goto errout;
+ }
+
+ attr = tb[NFULA_PREFIX];
+ if (attr) {
+ err = nfnl_log_msg_set_prefix(msg, nla_data(attr));
+ if (err < 0)
+ goto errout;
+ }
+
+ attr = tb[NFULA_UID];
+ if (attr)
+ nfnl_log_msg_set_uid(msg, ntohl(nla_get_u32(attr)));
+
+ attr = tb[NFULA_GID];
+ if (attr)
+ nfnl_log_msg_set_gid(msg, ntohl(nla_get_u32(attr)));
+
+ attr = tb[NFULA_SEQ];
+ if (attr)
+ nfnl_log_msg_set_seq(msg, ntohl(nla_get_u32(attr)));
+
+ attr = tb[NFULA_SEQ_GLOBAL];
+ if (attr)
+ nfnl_log_msg_set_seq_global(msg, ntohl(nla_get_u32(attr)));
+
+ return msg;
+
+errout:
+ nfnl_log_msg_put(msg);
+ return NULL;
+}
+
+static int log_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
+ struct nlmsghdr *nlh, struct nl_parser_param *pp)
+{
+ struct nfnl_log_msg *msg;
+ int err;
+
+ msg = nfnlmsg_log_msg_parse(nlh);
+ if (log == NULL)
+ goto errout_errno;
+
+ err = pp->pp_cb((struct nl_object *) msg, pp);
+ if (err < 0)
+ goto errout;
+
+ err = P_ACCEPT;
+
+errout:
+ nfnl_log_msg_put(msg);
+ return err;
+
+errout_errno:
+ err = nl_get_errno();
+ goto errout;
+}
+
+/** @} */
+
+#define NFNLMSG_LOG_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_ULOG, (type))
+static struct nl_cache_ops nfnl_log_msg_ops = {
+ .co_name = "netfilter/log_msg",
+ .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_msg_obj_ops,
+};
+
+static void __init log_msg_init(void)
+{
+ nl_cache_mngt_register(&nfnl_log_msg_ops);
+}
+
+static void __exit log_msg_exit(void)
+{
+ nl_cache_mngt_unregister(&nfnl_log_msg_ops);
+}
+
+/** @} */
diff --git a/lib/netfilter/log_msg_obj.c b/lib/netfilter/log_msg_obj.c
new file mode 100644
index 0000000..ee85090
--- /dev/null
+++ b/lib/netfilter/log_msg_obj.c
@@ -0,0 +1,456 @@
+/*
+ * lib/netfilter/log_msg_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/netfilter.h>
+#include <netlink/netfilter/log_msg.h>
+
+/** @cond SKIP */
+#define LOG_MSG_ATTR_FAMILY (1UL << 0)
+#define LOG_MSG_ATTR_HWPROTO (1UL << 1)
+#define LOG_MSG_ATTR_HOOK (1UL << 2)
+#define LOG_MSG_ATTR_MARK (1UL << 3)
+#define LOG_MSG_ATTR_TIMESTAMP (1UL << 4)
+#define LOG_MSG_ATTR_INDEV (1UL << 5)
+#define LOG_MSG_ATTR_OUTDEV (1UL << 6)
+#define LOG_MSG_ATTR_PHYSINDEV (1UL << 7)
+#define LOG_MSG_ATTR_PHYSOUTDEV (1UL << 8)
+#define LOG_MSG_ATTR_HWADDR (1UL << 9)
+#define LOG_MSG_ATTR_PAYLOAD (1UL << 10)
+#define LOG_MSG_ATTR_PREFIX (1UL << 11)
+#define LOG_MSG_ATTR_UID (1UL << 12)
+#define LOG_MSG_ATTR_GID (1UL << 13)
+#define LOG_MSG_ATTR_SEQ (1UL << 14)
+#define LOG_MSG_ATTR_SEQ_GLOBAL (1UL << 15)
+/** @endcond */
+
+static void log_msg_free_data(struct nl_object *c)
+{
+ struct nfnl_log_msg *msg = (struct nfnl_log_msg *) c;
+
+ if (msg == NULL)
+ return;
+
+ free(msg->log_msg_payload);
+ free(msg->log_msg_prefix);
+}
+
+static int log_msg_clone(struct nl_object *_dst, struct nl_object *_src)
+{
+ struct nfnl_log_msg *dst = (struct nfnl_log_msg *) _dst;
+ struct nfnl_log_msg *src = (struct nfnl_log_msg *) _src;
+ int err;
+
+ if (src->log_msg_payload) {
+ err = nfnl_log_msg_set_payload(dst, src->log_msg_payload,
+ src->log_msg_payload_len);
+ if (err < 0)
+ goto errout;
+ }
+
+ if (src->log_msg_prefix) {
+ err = nfnl_log_msg_set_prefix(dst, src->log_msg_prefix);
+ if (err < 0)
+ goto errout;
+ }
+
+ return 0;
+errout:
+ return err;
+}
+
+static int log_msg_dump(struct nl_object *a, struct nl_dump_params *p)
+{
+ struct nfnl_log_msg *msg = (struct nfnl_log_msg *) a;
+ struct nl_cache *link_cache;
+ char buf[64];
+
+ link_cache = nl_cache_mngt_require("route/link");
+
+ if (msg->ce_mask & LOG_MSG_ATTR_PREFIX)
+ dp_dump(p, "%s", msg->log_msg_prefix);
+
+ if (msg->ce_mask & LOG_MSG_ATTR_INDEV) {
+ if (link_cache)
+ dp_dump(p, "IN=%s ",
+ rtnl_link_i2name(link_cache,
+ msg->log_msg_indev,
+ buf, sizeof(buf)));
+ else
+ dp_dump(p, "IN=%d ", msg->log_msg_indev);
+ }
+
+ if (msg->ce_mask & LOG_MSG_ATTR_PHYSINDEV) {
+ if (link_cache)
+ dp_dump(p, "PHYSIN=%s ",
+ rtnl_link_i2name(link_cache,
+ msg->log_msg_physindev,
+ buf, sizeof(buf)));
+ else
+ dp_dump(p, "IN=%d ", msg->log_msg_physindev);
+ }
+
+ if (msg->ce_mask & LOG_MSG_ATTR_OUTDEV) {
+ if (link_cache)
+ dp_dump(p, "OUT=%s ",
+ rtnl_link_i2name(link_cache,
+ msg->log_msg_outdev,
+ buf, sizeof(buf)));
+ else
+ dp_dump(p, "OUT=%d ", msg->log_msg_outdev);
+ }
+
+ if (msg->ce_mask & LOG_MSG_ATTR_PHYSOUTDEV) {
+ if (link_cache)
+ dp_dump(p, "PHYSOUT=%s ",
+ rtnl_link_i2name(link_cache,
+ msg->log_msg_physoutdev,
+ buf, sizeof(buf)));
+ else
+ dp_dump(p, "PHYSOUT=%d ", msg->log_msg_physoutdev);
+ }
+
+ if (msg->ce_mask & LOG_MSG_ATTR_HWADDR) {
+ int i;
+
+ dp_dump(p, "MAC");
+ for (i = 0; i < msg->log_msg_hwaddr_len; i++)
+ dp_dump(p, "%c%02x", i?':':'=', msg->log_msg_hwaddr[i]);
+ dp_dump(p, " ");
+ }
+
+ /* FIXME: parse the payload to get iptables LOG compatible format */
+
+ if (msg->ce_mask & LOG_MSG_ATTR_FAMILY)
+ dp_dump(p, "FAMILY=%s ",
+ nl_af2str(msg->log_msg_family, buf, sizeof(buf)));
+
+ if (msg->ce_mask & LOG_MSG_ATTR_HWPROTO)
+ dp_dump(p, "HWPROTO=%s ",
+ nl_ether_proto2str(ntohs(msg->log_msg_hwproto),
+ buf, sizeof(buf)));
+
+ if (msg->ce_mask & LOG_MSG_ATTR_HOOK)
+ dp_dump(p, "HOOK=%s ",
+ nfnl_inet_hook2str(msg->log_msg_hook,
+ buf, sizeof(buf)));
+
+ if (msg->ce_mask & LOG_MSG_ATTR_MARK)
+ dp_dump(p, "MARK=%u ", msg->log_msg_mark);
+
+ if (msg->ce_mask & LOG_MSG_ATTR_PAYLOAD)
+ dp_dump(p, "PAYLOADLEN=%d ", msg->log_msg_payload_len);
+
+ if (msg->ce_mask & LOG_MSG_ATTR_UID)
+ dp_dump(p, "UID=%u ", msg->log_msg_uid);
+
+ if (msg->ce_mask & LOG_MSG_ATTR_GID)
+ dp_dump(p, "GID=%u ", msg->log_msg_gid);
+
+ if (msg->ce_mask & LOG_MSG_ATTR_SEQ)
+ dp_dump(p, "SEQ=%d ", msg->log_msg_seq);
+
+ if (msg->ce_mask & LOG_MSG_ATTR_SEQ_GLOBAL)
+ dp_dump(p, "SEQGLOBAL=%d ", msg->log_msg_seq_global);
+
+ dp_dump(p, "\n");
+
+ return 1;
+}
+
+/**
+ * @name Allocation/Freeing
+ * @{
+ */
+
+struct nfnl_log_msg *nfnl_log_msg_alloc(void)
+{
+ return (struct nfnl_log_msg *) nl_object_alloc(&log_msg_obj_ops);
+}
+
+void nfnl_log_msg_get(struct nfnl_log_msg *msg)
+{
+ nl_object_get((struct nl_object *) msg);
+}
+
+void nfnl_log_msg_put(struct nfnl_log_msg *msg)
+{
+ nl_object_put((struct nl_object *) msg);
+}
+
+/** @} */
+
+/**
+ * @name Attributes
+ * @{
+ */
+
+void nfnl_log_msg_set_family(struct nfnl_log_msg *msg, uint8_t family)
+{
+ msg->log_msg_family = family;
+ msg->ce_mask |= LOG_MSG_ATTR_FAMILY;
+}
+
+uint8_t nfnl_log_msg_get_family(const struct nfnl_log_msg *msg)
+{
+ if (msg->ce_mask & LOG_MSG_ATTR_FAMILY)
+ return msg->log_msg_family;
+ else
+ return AF_UNSPEC;
+}
+
+void nfnl_log_msg_set_hwproto(struct nfnl_log_msg *msg, uint16_t hwproto)
+{
+ msg->log_msg_hwproto = hwproto;
+ msg->ce_mask |= LOG_MSG_ATTR_HWPROTO;
+}
+
+int nfnl_log_msg_test_hwproto(const struct nfnl_log_msg *msg)
+{
+ return !!(msg->ce_mask & LOG_MSG_ATTR_HWPROTO);
+}
+
+uint16_t nfnl_log_msg_get_hwproto(const struct nfnl_log_msg *msg)
+{
+ return msg->log_msg_hwproto;
+}
+
+void nfnl_log_msg_set_hook(struct nfnl_log_msg *msg, uint8_t hook)
+{
+ msg->log_msg_hook = hook;
+ msg->ce_mask |= LOG_MSG_ATTR_HOOK;
+}
+
+int nfnl_log_msg_test_hook(const struct nfnl_log_msg *msg)
+{
+ return !!(msg->ce_mask & LOG_MSG_ATTR_HOOK);
+}
+
+uint8_t nfnl_log_msg_get_hook(const struct nfnl_log_msg *msg)
+{
+ return msg->log_msg_hook;
+}
+
+void nfnl_log_msg_set_mark(struct nfnl_log_msg *msg, uint32_t mark)
+{
+ msg->log_msg_mark = mark;
+ msg->ce_mask |= LOG_MSG_ATTR_MARK;
+}
+
+int nfnl_log_msg_test_mark(const struct nfnl_log_msg *msg)
+{
+ return !!(msg->ce_mask & LOG_MSG_ATTR_MARK);
+}
+
+uint32_t nfnl_log_msg_get_mark(const struct nfnl_log_msg *msg)
+{
+ return msg->log_msg_mark;
+}
+
+void nfnl_log_msg_set_timestamp(struct nfnl_log_msg *msg, struct timeval *tv)
+{
+ msg->log_msg_timestamp.tv_sec = tv->tv_sec;
+ msg->log_msg_timestamp.tv_usec = tv->tv_usec;
+ msg->ce_mask |= LOG_MSG_ATTR_TIMESTAMP;
+}
+
+const struct timeval *nfnl_log_msg_get_timestamp(const struct nfnl_log_msg *msg)
+{
+ if (!(msg->ce_mask & LOG_MSG_ATTR_TIMESTAMP))
+ return NULL;
+ return &msg->log_msg_timestamp;
+}
+
+void nfnl_log_msg_set_indev(struct nfnl_log_msg *msg, uint32_t indev)
+{
+ msg->log_msg_indev = indev;
+ msg->ce_mask |= LOG_MSG_ATTR_INDEV;
+}
+
+uint32_t nfnl_log_msg_get_indev(const struct nfnl_log_msg *msg)
+{
+ return msg->log_msg_indev;
+}
+
+void nfnl_log_msg_set_outdev(struct nfnl_log_msg *msg, uint32_t outdev)
+{
+ msg->log_msg_outdev = outdev;
+ msg->ce_mask |= LOG_MSG_ATTR_OUTDEV;
+}
+
+uint32_t nfnl_log_msg_get_outdev(const struct nfnl_log_msg *msg)
+{
+ return msg->log_msg_outdev;
+}
+
+void nfnl_log_msg_set_physindev(struct nfnl_log_msg *msg, uint32_t physindev)
+{
+ msg->log_msg_physindev = physindev;
+ msg->ce_mask |= LOG_MSG_ATTR_PHYSINDEV;
+}
+
+uint32_t nfnl_log_msg_get_physindev(const struct nfnl_log_msg *msg)
+{
+ return msg->log_msg_physindev;
+}
+
+void nfnl_log_msg_set_physoutdev(struct nfnl_log_msg *msg, uint32_t physoutdev)
+{
+ msg->log_msg_physoutdev = physoutdev;
+ msg->ce_mask |= LOG_MSG_ATTR_PHYSOUTDEV;
+}
+
+uint32_t nfnl_log_msg_get_physoutdev(const struct nfnl_log_msg *msg)
+{
+ return msg->log_msg_physoutdev;
+}
+
+void nfnl_log_msg_set_hwaddr(struct nfnl_log_msg *msg, uint8_t *hwaddr, int len)
+{
+ if (len > sizeof(msg->log_msg_hwaddr))
+ len = sizeof(msg->log_msg_hwaddr);
+ msg->log_msg_hwaddr_len = len;
+ memcpy(msg->log_msg_hwaddr, hwaddr, len);
+ msg->ce_mask |= LOG_MSG_ATTR_HWADDR;
+}
+
+const uint8_t *nfnl_log_msg_get_hwaddr(const struct nfnl_log_msg *msg, int *len)
+{
+ if (!(msg->ce_mask & LOG_MSG_ATTR_HWADDR)) {
+ *len = 0;
+ return NULL;
+ }
+
+ *len = msg->log_msg_hwaddr_len;
+ return msg->log_msg_hwaddr;
+}
+
+int nfnl_log_msg_set_payload(struct nfnl_log_msg *msg, uint8_t *payload, int len)
+{
+ free(msg->log_msg_payload);
+ msg->log_msg_payload = malloc(len);
+ if (!msg->log_msg_payload)
+ return nl_errno(ENOMEM);
+
+ memcpy(msg->log_msg_payload, payload, len);
+ msg->log_msg_payload_len = len;
+ msg->ce_mask |= LOG_MSG_ATTR_PAYLOAD;
+ return 0;
+}
+
+const void *nfnl_log_msg_get_payload(const struct nfnl_log_msg *msg, int *len)
+{
+ if (!(msg->ce_mask & LOG_MSG_ATTR_PAYLOAD)) {
+ *len = 0;
+ return NULL;
+ }
+
+ *len = msg->log_msg_payload_len;
+ return msg->log_msg_payload;
+}
+
+int nfnl_log_msg_set_prefix(struct nfnl_log_msg *msg, void *prefix)
+{
+ free(msg->log_msg_prefix);
+ msg->log_msg_prefix = strdup(prefix);
+ if (!msg->log_msg_prefix)
+ return nl_errno(ENOMEM);
+
+ msg->ce_mask |= LOG_MSG_ATTR_PREFIX;
+ return 0;
+}
+
+const char *nfnl_log_msg_get_prefix(const struct nfnl_log_msg *msg)
+{
+ return msg->log_msg_prefix;
+}
+
+void nfnl_log_msg_set_uid(struct nfnl_log_msg *msg, uint32_t uid)
+{
+ msg->log_msg_uid = uid;
+ msg->ce_mask |= LOG_MSG_ATTR_UID;
+}
+
+int nfnl_log_msg_test_uid(const struct nfnl_log_msg *msg)
+{
+ return !!(msg->ce_mask & LOG_MSG_ATTR_UID);
+}
+
+uint32_t nfnl_log_msg_get_uid(const struct nfnl_log_msg *msg)
+{
+ return msg->log_msg_uid;
+}
+
+void nfnl_log_msg_set_gid(struct nfnl_log_msg *msg, uint32_t gid)
+{
+ msg->log_msg_gid = gid;
+ msg->ce_mask |= LOG_MSG_ATTR_GID;
+}
+
+int nfnl_log_msg_test_gid(const struct nfnl_log_msg *msg)
+{
+ return !!(msg->ce_mask & LOG_MSG_ATTR_GID);
+}
+
+uint32_t nfnl_log_msg_get_gid(const struct nfnl_log_msg *msg)
+{
+ return msg->log_msg_gid;
+}
+
+
+void nfnl_log_msg_set_seq(struct nfnl_log_msg *msg, uint32_t seq)
+{
+ msg->log_msg_seq = seq;
+ msg->ce_mask |= LOG_MSG_ATTR_SEQ;
+}
+
+int nfnl_log_msg_test_seq(const struct nfnl_log_msg *msg)
+{
+ return !!(msg->ce_mask & LOG_MSG_ATTR_SEQ);
+}
+
+uint32_t nfnl_log_msg_get_seq(const struct nfnl_log_msg *msg)
+{
+ return msg->log_msg_seq;
+}
+
+void nfnl_log_msg_set_seq_global(struct nfnl_log_msg *msg, uint32_t seq_global)
+{
+ msg->log_msg_seq_global = seq_global;
+ msg->ce_mask |= LOG_MSG_ATTR_SEQ_GLOBAL;
+}
+
+int nfnl_log_msg_test_seq_global(const struct nfnl_log_msg *msg)
+{
+ return !!(msg->ce_mask & LOG_MSG_ATTR_SEQ_GLOBAL);
+}
+
+uint32_t nfnl_log_msg_get_seq_global(const struct nfnl_log_msg *msg)
+{
+ return msg->log_msg_seq_global;
+}
+
+/** @} */
+
+struct nl_object_ops log_msg_obj_ops = {
+ .oo_name = "netfilter/log_msg",
+ .oo_size = sizeof(struct nfnl_log_msg),
+ .oo_free_data = log_msg_free_data,
+ .oo_clone = log_msg_clone,
+ .oo_dump[NL_DUMP_BRIEF] = log_msg_dump,
+ .oo_dump[NL_DUMP_FULL] = log_msg_dump,
+ .oo_dump[NL_DUMP_STATS] = log_msg_dump,
+};
+
+/** @} */
diff --git a/lib/netfilter/log_obj.c b/lib/netfilter/log_obj.c
index 0e4411e..ce65443 100644
--- a/lib/netfilter/log_obj.c
+++ b/lib/netfilter/log_obj.c
@@ -9,6 +9,7 @@
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
* Copyright (c) 2007 Philip Craig <philipc@snapgear.com>
* Copyright (c) 2007 Secure Computing Corporation
+ * Copyright (c) 2008 Patrick McHardy <kaber@trash.net>
*/
#include <netlink-local.h>
@@ -16,152 +17,63 @@
#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_GID (1UL << 13)
-#define LOG_ATTR_SEQ (1UL << 14)
-#define LOG_ATTR_SEQ_GLOBAL (1UL << 15)
+#define LOG_ATTR_GROUP (1UL << 0)
+#define LOG_ATTR_COPY_MODE (1UL << 1)
+#define LOG_ATTR_COPY_RANGE (1UL << 3)
+#define LOG_ATTR_FLUSH_TIMEOUT (1UL << 4)
+#define LOG_ATTR_ALLOC_SIZE (1UL << 5)
+#define LOG_ATTR_QUEUE_THRESHOLD (1UL << 6)
+
/** @endcond */
-static void log_free_data(struct nl_object *c)
+static int nfnl_log_dump(struct nl_object *a, struct nl_dump_params *p)
{
- struct nfnl_log *log = (struct nfnl_log *) c;
+ struct nfnl_log *log = (struct nfnl_log *) a;
+ char buf[64];
- if (log == NULL)
- return;
+ if (log->ce_mask & LOG_ATTR_GROUP)
+ dp_dump(p, "group=%u ", log->log_group);
- free(log->log_payload);
- free(log->log_prefix);
-}
+ if (log->ce_mask & LOG_ATTR_COPY_MODE)
+ dp_dump(p, "copy_mode=%s ",
+ nfnl_log_copy_mode2str(log->log_copy_mode,
+ buf, sizeof(buf)));
-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;
-}
+ if (log->ce_mask & LOG_ATTR_COPY_RANGE)
+ dp_dump(p, "copy_range=%u ", log->log_copy_range);
-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];
+ if (log->ce_mask & LOG_ATTR_FLUSH_TIMEOUT)
+ dp_dump(p, "flush_timeout=%u ", log->log_flush_timeout);
+
+ if (log->ce_mask & LOG_ATTR_ALLOC_SIZE)
+ dp_dump(p, "alloc_size=%u ", log->log_alloc_size);
- 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_UID)
- dp_dump(p, "UID=%u ", log->log_uid);
-
- if (log->ce_mask & LOG_ATTR_GID)
- dp_dump(p, "GID=%u ", log->log_gid);
-
- 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);
+ if (log->ce_mask & LOG_ATTR_QUEUE_THRESHOLD)
+ dp_dump(p, "queue_threshold=%u ", log->log_queue_threshold);
dp_dump(p, "\n");
return 1;
}
+static struct trans_tbl copy_modes[] = {
+ __ADD(NFNL_LOG_COPY_NONE, none)
+ __ADD(NFNL_LOG_COPY_META, meta)
+ __ADD(NFNL_LOG_COPY_PACKET, packet)
+};
+
+char *nfnl_log_copy_mode2str(enum nfnl_log_copy_mode copy_mode, char *buf,
+ size_t len)
+{
+ return __type2str(copy_mode, buf, len, copy_modes,
+ ARRAY_SIZE(copy_modes));
+}
+
+enum nfnl_log_copy_mode nfnl_log_str2copy_mode(const char *name)
+{
+ return __str2type(name, copy_modes, ARRAY_SIZE(copy_modes));
+}
+
/**
* @name Allocation/Freeing
* @{
@@ -189,249 +101,172 @@ void nfnl_log_put(struct nfnl_log *log)
* @{
*/
-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)
+void nfnl_log_set_group(struct nfnl_log *log, uint16_t group)
{
- return !!(log->ce_mask & LOG_ATTR_MARK);
+ log->log_group = group;
+ log->ce_mask |= LOG_ATTR_GROUP;
}
-uint32_t nfnl_log_get_mark(const struct nfnl_log *log)
+int nfnl_log_test_group(const struct nfnl_log *log)
{
- return log->log_mark;
+ return !!(log->ce_mask & LOG_ATTR_GROUP);
}
-void nfnl_log_set_timestamp(struct nfnl_log *log, struct timeval *tv)
+uint16_t nfnl_log_get_group(const struct nfnl_log *log)
{
- log->log_timestamp.tv_sec = tv->tv_sec;
- log->log_timestamp.tv_usec = tv->tv_usec;
- log->ce_mask |= LOG_ATTR_TIMESTAMP;
+ return log->log_group;
}
-const struct timeval *nfnl_log_get_timestamp(const struct nfnl_log *log)
+void nfnl_log_set_copy_mode(struct nfnl_log *log, enum nfnl_log_copy_mode mode)
{
- if (!(log->ce_mask & LOG_ATTR_TIMESTAMP))
- return NULL;
- return &log->log_timestamp;
+ log->log_copy_mode = mode;
+ log->ce_mask |= LOG_ATTR_COPY_MODE;
}
-void nfnl_log_set_indev(struct nfnl_log *log, uint32_t indev)
+int nfnl_log_test_copy_mode(const struct nfnl_log *log)
{
- log->log_indev = indev;
- log->ce_mask |= LOG_ATTR_INDEV;
+ return !!(log->ce_mask & LOG_ATTR_COPY_MODE);
}
-uint32_t nfnl_log_get_indev(const struct nfnl_log *log)
+enum nfnl_log_copy_mode nfnl_log_get_copy_mode(const struct nfnl_log *log)
{
- return log->log_indev;
+ return log->log_copy_mode;
}
-void nfnl_log_set_outdev(struct nfnl_log *log, uint32_t outdev)
+void nfnl_log_set_copy_range(struct nfnl_log *log, uint32_t copy_range)
{
- log->log_outdev = outdev;
- log->ce_mask |= LOG_ATTR_OUTDEV;
+ log->log_copy_range = copy_range;
+ log->ce_mask |= LOG_ATTR_COPY_RANGE;
}
-uint32_t nfnl_log_get_outdev(const struct nfnl_log *log)
+int nfnl_log_test_copy_range(const struct nfnl_log *log)
{
- return log->log_outdev;
+ return !!(log->ce_mask & LOG_ATTR_COPY_RANGE);
}
-void nfnl_log_set_physindev(struct nfnl_log *log, uint32_t physindev)
+uint32_t nfnl_log_get_copy_range(const struct nfnl_log *log)
{
- log->log_physindev = physindev;
- log->ce_mask |= LOG_ATTR_PHYSINDEV;
+ return log->log_copy_range;
}
-uint32_t nfnl_log_get_physindev(const struct nfnl_log *log)
+void nfnl_log_set_flush_timeout(struct nfnl_log *log, uint32_t timeout)
{
- return log->log_physindev;
+ log->log_flush_timeout = timeout;
+ log->ce_mask |= LOG_ATTR_FLUSH_TIMEOUT;
}
-void nfnl_log_set_physoutdev(struct nfnl_log *log, uint32_t physoutdev)
+int nfnl_log_test_flush_timeout(const struct nfnl_log *log)
{
- log->log_physoutdev = physoutdev;
- log->ce_mask |= LOG_ATTR_PHYSOUTDEV;
+ return !!(log->ce_mask & LOG_ATTR_FLUSH_TIMEOUT);
}
-uint32_t nfnl_log_get_physoutdev(const struct nfnl_log *log)
+uint32_t nfnl_log_get_flush_timeout(const struct nfnl_log *log)
{
- return log->log_physoutdev;
+ return log->log_flush_timeout;
}
-void nfnl_log_set_hwaddr(struct nfnl_log *log, uint8_t *hwaddr, int len)
+void nfnl_log_set_alloc_size(struct nfnl_log *log, uint32_t alloc_size)
{
- 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;
+ log->log_alloc_size = alloc_size;
+ log->ce_mask |= LOG_ATTR_ALLOC_SIZE;
}
-const uint8_t *nfnl_log_get_hwaddr(const struct nfnl_log *log, int *len)
+int nfnl_log_test_alloc_size(const struct nfnl_log *log)
{
- if (!(log->ce_mask & LOG_ATTR_HWADDR)) {
- *len = 0;
- return NULL;
- }
-
- *len = log->log_hwaddr_len;
- return log->log_hwaddr;
+ return !!(log->ce_mask & LOG_ATTR_ALLOC_SIZE);
}
-int nfnl_log_set_payload(struct nfnl_log *log, uint8_t *payload, int len)
+uint32_t nfnl_log_get_alloc_size(const struct nfnl_log *log)
{
- 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;
+ return log->log_alloc_size;
}
-const void *nfnl_log_get_payload(const struct nfnl_log *log, int *len)
+void nfnl_log_set_queue_threshold(struct nfnl_log *log, uint32_t threshold)
{
- if (!(log->ce_mask & LOG_ATTR_PAYLOAD)) {
- *len = 0;
- return NULL;
- }
-
- *len = log->log_payload_len;
- return log->log_payload;
+ log->log_queue_threshold = threshold;
+ log->ce_mask |= LOG_ATTR_QUEUE_THRESHOLD;
}
-int nfnl_log_set_prefix(struct nfnl_log *log, void *prefix)
+int nfnl_log_test_queue_threshold(const struct nfnl_log *log)
{
- 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;
+ return !!(log->ce_mask & LOG_ATTR_QUEUE_THRESHOLD);
}
-const char *nfnl_log_get_prefix(const struct nfnl_log *log)
+uint32_t nfnl_log_get_queue_threshold(const struct nfnl_log *log)
{
- return log->log_prefix;
+ return log->log_queue_threshold;
}
-void nfnl_log_set_uid(struct nfnl_log *log, uint32_t uid)
+/* We don't actually use the flags for anything yet since the
+ * nfnetlog_log interface truly sucks - it only contains the
+ * flag value, but not mask, so we would have to make assumptions
+ * about the supported flags.
+ */
+void nfnl_log_set_flags(struct nfnl_log *log, unsigned int flags)
{
- log->log_uid = uid;
- log->ce_mask |= LOG_ATTR_UID;
+ log->log_flags |= flags;
+ log->log_flag_mask |= flags;
}
-int nfnl_log_test_uid(const struct nfnl_log *log)
+void nfnl_log_unset_flags(struct nfnl_log *log, unsigned int flags)
{
- return !!(log->ce_mask & LOG_ATTR_UID);
+ log->log_flags &= ~flags;
+ log->log_flag_mask |= flags;
}
-uint32_t nfnl_log_get_uid(const struct nfnl_log *log)
-{
- return log->log_uid;
-}
+static struct trans_tbl log_flags[] = {
+ __ADD(NFNL_LOG_FLAG_SEQ, seq)
+ __ADD(NFNL_LOG_FLAG_SEQ_GLOBAL, seq_global)
+};
-void nfnl_log_set_gid(struct nfnl_log *log, uint32_t gid)
+char *nfnl_log_flags2str(unsigned int flags, char *buf, size_t len)
{
- log->log_gid = gid;
- log->ce_mask |= LOG_ATTR_GID;
+ return __flags2str(flags, buf, len, log_flags, ARRAY_SIZE(log_flags));
}
-int nfnl_log_test_gid(const struct nfnl_log *log)
+unsigned int nfnl_log_str2flags(const char *name)
{
- return !!(log->ce_mask & LOG_ATTR_GID);
+ return __str2flags(name, log_flags, ARRAY_SIZE(log_flags));
}
-uint32_t nfnl_log_get_gid(const struct nfnl_log *log)
+static int nfnl_log_compare(struct nl_object *_a, struct nl_object *_b,
+ uint32_t attrs, int flags)
{
- return log->log_gid;
-}
-
+ struct nfnl_log *a = (struct nfnl_log *) _a;
+ struct nfnl_log *b = (struct nfnl_log *) _b;
+ int diff = 0;
-void nfnl_log_set_seq(struct nfnl_log *log, uint32_t seq)
-{
- log->log_seq = seq;
- log->ce_mask |= LOG_ATTR_SEQ;
-}
+#define NFNL_LOG_DIFF(ATTR, EXPR) \
+ ATTR_DIFF(attrs, LOG_ATTR_##ATTR, a, b, EXPR)
+#define NFNL_LOG_DIFF_VAL(ATTR, FIELD) \
+ NFNL_LOG_DIFF(ATTR, a->FIELD != b->FIELD)
-int nfnl_log_test_seq(const struct nfnl_log *log)
-{
- return !!(log->ce_mask & LOG_ATTR_SEQ);
-}
+ diff |= NFNL_LOG_DIFF_VAL(GROUP, log_group);
+ diff |= NFNL_LOG_DIFF_VAL(COPY_MODE, log_copy_mode);
+ diff |= NFNL_LOG_DIFF_VAL(COPY_RANGE, log_copy_range);
+ diff |= NFNL_LOG_DIFF_VAL(FLUSH_TIMEOUT, log_flush_timeout);
+ diff |= NFNL_LOG_DIFF_VAL(ALLOC_SIZE, log_alloc_size);
+ diff |= NFNL_LOG_DIFF_VAL(QUEUE_THRESHOLD, log_queue_threshold);
-uint32_t nfnl_log_get_seq(const struct nfnl_log *log)
-{
- return log->log_seq;
-}
+#undef NFNL_LOG_DIFF
+#undef NFNL_LOG_DIFF_VAL
-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;
+ return diff;
}
-int nfnl_log_test_seq_global(const struct nfnl_log *log)
-{
- return !!(log->ce_mask & LOG_ATTR_SEQ_GLOBAL);
-}
+static struct trans_tbl nfnl_log_attrs[] = {
+ __ADD(LOG_ATTR_GROUP, group)
+ __ADD(LOG_ATTR_COPY_MODE, copy_mode)
+ __ADD(LOG_ATTR_COPY_RANGE, copy_range)
+ __ADD(LOG_ATTR_FLUSH_TIMEOUT, flush_timeout)
+ __ADD(LOG_ATTR_ALLOC_SIZE, alloc_size)
+ __ADD(LOG_ATTR_QUEUE_THRESHOLD, queue_threshold)
+};
-uint32_t nfnl_log_get_seq_global(const struct nfnl_log *log)
+static char *nfnl_log_attrs2str(int attrs, char *buf, size_t len)
{
- return log->log_seq_global;
+ return __flags2str(attrs, buf, len, nfnl_log_attrs,
+ ARRAY_SIZE(nfnl_log_attrs));
}
/** @} */
@@ -439,11 +274,12 @@ uint32_t nfnl_log_get_seq_global(const struct nfnl_log *log)
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,
+ .oo_dump[NL_DUMP_BRIEF] = nfnl_log_dump,
+ .oo_dump[NL_DUMP_FULL] = nfnl_log_dump,
+ .oo_dump[NL_DUMP_STATS] = nfnl_log_dump,
+ .oo_compare = nfnl_log_compare,
+ .oo_attrs2str = nfnl_log_attrs2str,
+ .oo_id_attrs = LOG_ATTR_GROUP,
};
/** @} */
diff --git a/src/nf-log.c b/src/nf-log.c
index 2c100f8..d1f0ed6 100644
--- a/src/nf-log.c
+++ b/src/nf-log.c
@@ -43,8 +43,11 @@ int main(int argc, char *argv[])
struct nl_handle *nfnlh;
struct nl_handle *rtnlh;
struct nl_cache *link_cache;
+ struct nfnl_log *log;
+ enum nfnl_log_copy_mode copy_mode;
+ uint32_t copy_range;
int err = 1;
- int family, group;
+ int family;
if (nltool_init(argc, argv) < 0)
return -1;
@@ -58,7 +61,8 @@ int main(int argc, char *argv[])
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");
+ printf("Usage: nf-log family group [ copy_mode ] "
+ "[copy_range] \n");
return 2;
}
@@ -72,26 +76,52 @@ int main(int argc, char *argv[])
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;
- }
+
+ nfnl_log_pf_unbind(nfnlh, family);
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) {
+ log = nfnl_log_alloc();
+ if (log == NULL) {
fprintf(stderr, "%s\n", nl_geterror());
goto errout;
}
- if (nfnl_log_set_mode(nfnlh, 0, NFULNL_COPY_PACKET, 0xffff) < 0) {
+ nfnl_log_set_group(log, atoi(argv[2]));
+
+ copy_mode = NFNL_LOG_COPY_META;
+ if (argc > 3) {
+ copy_mode = nfnl_log_str2copy_mode(argv[3]);
+ if (copy_mode < 0) {
+ fprintf(stderr, "%s\n", nl_geterror());
+ goto errout;
+ }
+ }
+ nfnl_log_set_copy_mode(log, copy_mode);
+
+ copy_range = 0xFFFF;
+ if (argc > 4)
+ copy_mode = atoi(argv[4]);
+ nfnl_log_set_copy_range(log, copy_range);
+
+ if (nfnl_log_create(nfnlh, log) <0) {
fprintf(stderr, "%s\n", nl_geterror());
goto errout;
}
+ {
+ struct nl_dump_params dp = {
+ .dp_type = NL_DUMP_STATS,
+ .dp_fd = stdout,
+ .dp_dump_msgtype = 1,
+ };
+
+ printf("log params: ");
+ nl_object_dump((struct nl_object *) log, &dp);
+ }
+
rtnlh = nltool_alloc_handle();
if (rtnlh == NULL) {
goto errout_close;
@@ -134,9 +164,16 @@ int main(int argc, char *argv[])
}
}
+ nl_cache_mngt_unprovide(link_cache);
+ nl_cache_free(link_cache);
+
+ nfnl_log_put(log);
+
nl_close(rtnlh);
+ nl_handle_destroy(rtnlh);
errout_close:
nl_close(nfnlh);
+ nl_handle_destroy(nfnlh);
errout:
return err;
}
^ permalink raw reply related [flat|nested] 26+ messages in thread* Re: [LIBNL 07/09]: Split up nfnetlink_log into log and msg objects
2008-01-18 16:55 ` [LIBNL 07/09]: Split up nfnetlink_log into log and msg objects Patrick McHardy
@ 2008-01-21 8:05 ` Philip Craig
2008-01-21 9:45 ` Patrick McHardy
2008-02-07 12:11 ` Thomas Graf
1 sibling, 1 reply; 26+ messages in thread
From: Philip Craig @ 2008-01-21 8:05 UTC (permalink / raw)
To: Patrick McHardy; +Cc: tgraf, netfilter-devel
Patrick McHardy wrote:
> commit c566db4405200994482d36fac45089aba4e2360a
> Author: Patrick McHardy <kaber@trash.net>
> Date: Fri Jan 18 17:52:41 2008 +0100
>
> [LIBNL]: Split up nfnetlink_log into log and msg objects
>
> Split the nfnetlink_log code into two seperate objects, "netfilter/log"
> to represent logging instances and "netfilter/log_msg" to represent
> log messages. Also perform some function name unification for consistency
> with other libnl object types, mainly renaming nfnl_log_build_*_msg
> to nfnl_log_build_*_request.
>
> This changes the API in an incompatible way, but since this feature is
> new and the libnl netfilter headers haven't been installed so far,
> there shouldn't be any users affected by this.
>
> Signed-off-by: Patrick McHardy <kaber@trash.net>
Definitely an improvement, thanks. The pf bind/unbind are still handled
differently, but I guess they are too simple to warrant it and will
never get more attributes.
I hadn't noticed the missing headers because my cross compile
environment has its own custom install target.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [LIBNL 07/09]: Split up nfnetlink_log into log and msg objects
2008-01-21 8:05 ` Philip Craig
@ 2008-01-21 9:45 ` Patrick McHardy
0 siblings, 0 replies; 26+ messages in thread
From: Patrick McHardy @ 2008-01-21 9:45 UTC (permalink / raw)
To: Philip Craig; +Cc: tgraf, netfilter-devel
Philip Craig wrote:
> Patrick McHardy wrote:
>> commit c566db4405200994482d36fac45089aba4e2360a
>> Author: Patrick McHardy <kaber@trash.net>
>> Date: Fri Jan 18 17:52:41 2008 +0100
>>
>> [LIBNL]: Split up nfnetlink_log into log and msg objects
>>
>> Split the nfnetlink_log code into two seperate objects, "netfilter/log"
>> to represent logging instances and "netfilter/log_msg" to represent
>> log messages. Also perform some function name unification for consistency
>> with other libnl object types, mainly renaming nfnl_log_build_*_msg
>> to nfnl_log_build_*_request.
>>
>> This changes the API in an incompatible way, but since this feature is
>> new and the libnl netfilter headers haven't been installed so far,
>> there shouldn't be any users affected by this.
>>
>> Signed-off-by: Patrick McHardy <kaber@trash.net>
>
> Definitely an improvement, thanks. The pf bind/unbind are still handled
> differently, but I guess they are too simple to warrant it and will
> never get more attributes.
Yes, I kept those seperated from the log object because we can
subscribe to multiple families and this really didn't fit the
object model very well. I still hope to get rid of these within
the kernel some day.
> I hadn't noticed the missing headers because my cross compile
> environment has its own custom install target.
I was happy to discover it since this means we can change the
API without annoying users :)
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [LIBNL 07/09]: Split up nfnetlink_log into log and msg objects
2008-01-18 16:55 ` [LIBNL 07/09]: Split up nfnetlink_log into log and msg objects Patrick McHardy
2008-01-21 8:05 ` Philip Craig
@ 2008-02-07 12:11 ` Thomas Graf
1 sibling, 0 replies; 26+ messages in thread
From: Thomas Graf @ 2008-02-07 12:11 UTC (permalink / raw)
To: Patrick McHardy; +Cc: netfilter-devel, philipc
* Patrick McHardy <kaber@trash.net> 2008-01-18 17:55
> commit c566db4405200994482d36fac45089aba4e2360a
> Author: Patrick McHardy <kaber@trash.net>
> Date: Fri Jan 18 17:52:41 2008 +0100
>
> [LIBNL]: Split up nfnetlink_log into log and msg objects
>
> Split the nfnetlink_log code into two seperate objects, "netfilter/log"
> to represent logging instances and "netfilter/log_msg" to represent
> log messages. Also perform some function name unification for consistency
> with other libnl object types, mainly renaming nfnl_log_build_*_msg
> to nfnl_log_build_*_request.
Applied with a few whitespaces fixed. Thanks Patrick!
> This changes the API in an incompatible way, but since this feature is
> new and the libnl netfilter headers haven't been installed so far,
> there shouldn't be any users affected by this.
Yes, I agree.
^ permalink raw reply [flat|nested] 26+ messages in thread
* [LIBNL 08/09]: Support conntrack add/delete/query requests
2008-01-18 16:55 [LIBNL 00/09]: Netfilter update + minor fixes Patrick McHardy
` (6 preceding siblings ...)
2008-01-18 16:55 ` [LIBNL 07/09]: Split up nfnetlink_log into log and msg objects Patrick McHardy
@ 2008-01-18 16:55 ` Patrick McHardy
2008-01-21 8:39 ` Philip Craig
2008-02-07 12:14 ` Thomas Graf
2008-01-18 16:56 ` [LIBNL 09/09]: Install netfilter headers Patrick McHardy
8 siblings, 2 replies; 26+ messages in thread
From: Patrick McHardy @ 2008-01-18 16:55 UTC (permalink / raw)
To: tgraf; +Cc: Patrick McHardy, netfilter-devel, philipc
commit 5d2b826674d411f99e571fd35ad5722fed077e5e
Author: Patrick McHardy <kaber@trash.net>
Date: Fri Jan 18 17:53:14 2008 +0100
[LIBNL]: Support conntrack add/delete/query requests
Signed-off-by: Patrick McHardy <kaber@trash.net>
diff --git a/include/netlink/netfilter/ct.h b/include/netlink/netfilter/ct.h
index 965b869..f554017 100644
--- a/include/netlink/netfilter/ct.h
+++ b/include/netlink/netfilter/ct.h
@@ -39,6 +39,15 @@ extern void nfnl_ct_put(struct nfnl_ct *);
extern int nfnl_ct_dump_request(struct nl_handle *);
+extern struct nl_msg * nfnl_ct_build_add_request(const struct nfnl_ct *, int);
+extern int nfnl_ct_add(struct nl_handle *, const struct nfnl_ct *, int);
+
+extern struct nl_msg * nfnl_ct_build_delete_request(const struct nfnl_ct *, int);
+extern int nfnl_ct_delete(struct nl_handle *, const struct nfnl_ct *, int);
+
+extern struct nl_msg * nfnl_ct_build_query_request(const struct nfnl_ct *, int);
+extern int nfnl_ct_query(struct nl_handle *, const struct nfnl_ct *, int);
+
extern void nfnl_ct_set_family(struct nfnl_ct *, uint8_t);
extern uint8_t nfnl_ct_get_family(const struct nfnl_ct *);
diff --git a/lib/netfilter/ct.c b/lib/netfilter/ct.c
index e9df924..e16a606 100644
--- a/lib/netfilter/ct.c
+++ b/lib/netfilter/ct.c
@@ -9,6 +9,7 @@
* Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
* Copyright (c) 2007 Philip Craig <philipc@snapgear.com>
* Copyright (c) 2007 Secure Computing Corporation
+ * Copyright (c= 2008 Patrick McHardy <kaber@trash.net>
*/
/**
@@ -388,6 +389,158 @@ static int ct_request_update(struct nl_cache *c, struct nl_handle *h)
return nfnl_ct_dump_request(h);
}
+static int nfnl_ct_build_tuple(struct nl_msg *msg, const struct nfnl_ct *ct,
+ int repl)
+{
+ struct nlattr *tuple, *ip, *proto;
+ struct nl_addr *addr;
+ int family;
+
+ family = nfnl_ct_get_family(ct);
+
+ tuple = nla_nest_start(msg, repl ? CTA_TUPLE_REPLY : CTA_TUPLE_ORIG);
+ if (!tuple)
+ goto nla_put_failure;
+
+ ip = nla_nest_start(msg, CTA_TUPLE_IP);
+ if (!ip)
+ goto nla_put_failure;
+
+ addr = nfnl_ct_get_src(ct, repl);
+ if (addr)
+ NLA_PUT_ADDR(msg,
+ family == AF_INET ? CTA_IP_V4_SRC : CTA_IP_V6_SRC,
+ addr);
+
+ addr = nfnl_ct_get_dst(ct, repl);
+ if (addr)
+ NLA_PUT_ADDR(msg,
+ family == AF_INET ? CTA_IP_V4_DST : CTA_IP_V6_DST,
+ addr);
+
+ nla_nest_end(msg, ip);
+
+ proto = nla_nest_start(msg, CTA_TUPLE_PROTO);
+ if (!proto)
+ goto nla_put_failure;
+
+ if (nfnl_ct_test_proto(ct))
+ NLA_PUT_U8(msg, CTA_PROTO_NUM, nfnl_ct_get_proto(ct));
+
+ if (nfnl_ct_test_src_port(ct, repl))
+ NLA_PUT_U16(msg, CTA_PROTO_SRC_PORT,
+ nfnl_ct_get_src_port(ct, repl));
+
+ if (nfnl_ct_test_dst_port(ct, repl))
+ NLA_PUT_U16(msg, CTA_PROTO_DST_PORT,
+ nfnl_ct_get_dst_port(ct, repl));
+
+ if (nfnl_ct_test_icmp_id(ct, repl))
+ NLA_PUT_U16(msg, CTA_PROTO_ICMP_ID,
+ nfnl_ct_get_icmp_id(ct, repl));
+
+ if (nfnl_ct_test_icmp_type(ct, repl))
+ NLA_PUT_U8(msg, CTA_PROTO_ICMP_TYPE,
+ nfnl_ct_get_icmp_type(ct, repl));
+
+ if (nfnl_ct_test_icmp_code(ct, repl))
+ NLA_PUT_U8(msg, CTA_PROTO_ICMP_CODE,
+ nfnl_ct_get_icmp_code(ct, repl));
+
+ nla_nest_end(msg, proto);
+
+ nla_nest_end(msg, tuple);
+ return 0;
+
+nla_put_failure:
+ return -1;
+}
+
+static struct nl_msg *nfnl_ct_build_message(const struct nfnl_ct *ct, int cmd, int flags)
+{
+ struct nl_msg *msg;
+
+ msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_CTNETLINK, cmd, flags,
+ nfnl_ct_get_family(ct), 0);
+ if (msg == NULL)
+ return NULL;
+
+ if (nfnl_ct_build_tuple(msg, ct, 0) < 0)
+ goto err_out;
+
+ return msg;
+
+err_out:
+ nlmsg_free(msg);
+ return NULL;
+}
+
+struct nl_msg *nfnl_ct_build_add_request(const struct nfnl_ct *ct, int flags)
+{
+ return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_NEW, flags);
+}
+
+int nfnl_ct_add(struct nl_handle *h, const struct nfnl_ct *ct, int flags)
+{
+ struct nl_msg *msg;
+ int err;
+
+ msg = nfnl_ct_build_add_request(ct, flags);
+ if (msg == NULL)
+ return nl_errno(ENOMEM);
+
+ err = nl_send_auto_complete(h, msg);
+ nlmsg_free(msg);
+ if (err < 0)
+ return err;
+
+ return nl_wait_for_ack(h);
+}
+
+struct nl_msg *nfnl_ct_build_delete_request(const struct nfnl_ct *ct, int flags)
+{
+ return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_DELETE, flags);
+}
+
+int nfnl_ct_del(struct nl_handle *h, const struct nfnl_ct *ct, int flags)
+{
+ struct nl_msg *msg;
+ int err;
+
+ msg = nfnl_ct_build_delete_request(ct, flags);
+ if (msg == NULL)
+ return nl_errno(ENOMEM);
+
+ err = nl_send_auto_complete(h, msg);
+ nlmsg_free(msg);
+ if (err < 0)
+ return err;
+
+ return nl_wait_for_ack(h);
+}
+
+struct nl_msg *nfnl_ct_build_query_request(const struct nfnl_ct *ct, int flags)
+{
+ return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_GET, flags);
+}
+
+int nfnl_ct_query(struct nl_handle *h, const struct nfnl_ct *ct, int flags)
+{
+ struct nl_msg *msg;
+ int err;
+
+ msg = nfnl_ct_build_query_request(ct, flags);
+ if (msg == NULL)
+ return nl_errno(ENOMEM);
+
+ err = nl_send_auto_complete(h, msg);
+ nlmsg_free(msg);
+ if (err < 0)
+ return err;
+
+ return nl_wait_for_ack(h);
+}
+
/**
* @name Cache Management
* @{
^ permalink raw reply related [flat|nested] 26+ messages in thread* Re: [LIBNL 08/09]: Support conntrack add/delete/query requests
2008-01-18 16:55 ` [LIBNL 08/09]: Support conntrack add/delete/query requests Patrick McHardy
@ 2008-01-21 8:39 ` Philip Craig
2008-01-21 9:46 ` Patrick McHardy
2008-02-07 12:14 ` Thomas Graf
1 sibling, 1 reply; 26+ messages in thread
From: Philip Craig @ 2008-01-21 8:39 UTC (permalink / raw)
To: Patrick McHardy; +Cc: tgraf, netfilter-devel
Patrick McHardy wrote:
> commit 5d2b826674d411f99e571fd35ad5722fed077e5e
> Author: Patrick McHardy <kaber@trash.net>
> Date: Fri Jan 18 17:53:14 2008 +0100
>
> [LIBNL]: Support conntrack add/delete/query requests
>
> Signed-off-by: Patrick McHardy <kaber@trash.net>
>
> diff --git a/include/netlink/netfilter/ct.h b/include/netlink/netfilter/ct.h
> index 965b869..f554017 100644
> --- a/include/netlink/netfilter/ct.h
> +++ b/include/netlink/netfilter/ct.h
> @@ -39,6 +39,15 @@ extern void nfnl_ct_put(struct nfnl_ct *);
>
> extern int nfnl_ct_dump_request(struct nl_handle *);
This was just a quick and dirty dump request. nfnl_ct_query covers this now,
so we can delete it.
> +extern struct nl_msg * nfnl_ct_build_add_request(const struct nfnl_ct *, int);
> +extern int nfnl_ct_add(struct nl_handle *, const struct nfnl_ct *, int);
> +
> +extern struct nl_msg * nfnl_ct_build_delete_request(const struct nfnl_ct *, int);
> +extern int nfnl_ct_delete(struct nl_handle *, const struct nfnl_ct *, int);
> +
> +extern struct nl_msg * nfnl_ct_build_query_request(const struct nfnl_ct *, int);
> +extern int nfnl_ct_query(struct nl_handle *, const struct nfnl_ct *, int);
> +
> extern void nfnl_ct_set_family(struct nfnl_ct *, uint8_t);
> extern uint8_t nfnl_ct_get_family(const struct nfnl_ct *);
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [LIBNL 08/09]: Support conntrack add/delete/query requests
2008-01-21 8:39 ` Philip Craig
@ 2008-01-21 9:46 ` Patrick McHardy
2008-01-21 10:53 ` Philip Craig
0 siblings, 1 reply; 26+ messages in thread
From: Patrick McHardy @ 2008-01-21 9:46 UTC (permalink / raw)
To: Philip Craig; +Cc: tgraf, netfilter-devel
Philip Craig wrote:
> Patrick McHardy wrote:
>> commit 5d2b826674d411f99e571fd35ad5722fed077e5e
>> Author: Patrick McHardy <kaber@trash.net>
>> Date: Fri Jan 18 17:53:14 2008 +0100
>>
>> [LIBNL]: Support conntrack add/delete/query requests
>>
>> Signed-off-by: Patrick McHardy <kaber@trash.net>
>>
>> diff --git a/include/netlink/netfilter/ct.h b/include/netlink/netfilter/ct.h
>> index 965b869..f554017 100644
>> --- a/include/netlink/netfilter/ct.h
>> +++ b/include/netlink/netfilter/ct.h
>> @@ -39,6 +39,15 @@ extern void nfnl_ct_put(struct nfnl_ct *);
>>
>> extern int nfnl_ct_dump_request(struct nl_handle *);
>
> This was just a quick and dirty dump request. nfnl_ct_query covers this now,
> so we can delete it.
nfnl_ct_query doesn't perform a full dump, so this still looks useful.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [LIBNL 08/09]: Support conntrack add/delete/query requests
2008-01-21 9:46 ` Patrick McHardy
@ 2008-01-21 10:53 ` Philip Craig
2008-01-21 10:55 ` Patrick McHardy
0 siblings, 1 reply; 26+ messages in thread
From: Philip Craig @ 2008-01-21 10:53 UTC (permalink / raw)
To: Patrick McHardy; +Cc: tgraf, netfilter-devel
Patrick McHardy wrote:
> nfnl_ct_query doesn't perform a full dump, so this still looks useful.
Will this do a full dump?
nfnl_ct_query(handle, nfnl_ct_alloc(), NLM_F_DUMP);
I'm okay with leaving it in there, I just didn't want to keep functions
that none of the other objects in libnl have if they aren't really needed.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [LIBNL 08/09]: Support conntrack add/delete/query requests
2008-01-21 10:53 ` Philip Craig
@ 2008-01-21 10:55 ` Patrick McHardy
0 siblings, 0 replies; 26+ messages in thread
From: Patrick McHardy @ 2008-01-21 10:55 UTC (permalink / raw)
To: Philip Craig; +Cc: tgraf, netfilter-devel
Philip Craig wrote:
> Patrick McHardy wrote:
>> nfnl_ct_query doesn't perform a full dump, so this still looks useful.
>
> Will this do a full dump?
> nfnl_ct_query(handle, nfnl_ct_alloc(), NLM_F_DUMP);
Yes, but the query function expects a conntrack object with tuples
etc. to build the message, so its unnecessary complicated to use
it for a full dump.
> I'm okay with leaving it in there, I just didn't want to keep functions
> that none of the other objects in libnl have if they aren't really needed.
In this case I think its preferrable to keep it around.
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [LIBNL 08/09]: Support conntrack add/delete/query requests
2008-01-18 16:55 ` [LIBNL 08/09]: Support conntrack add/delete/query requests Patrick McHardy
2008-01-21 8:39 ` Philip Craig
@ 2008-02-07 12:14 ` Thomas Graf
2008-02-19 12:32 ` Patrick McHardy
1 sibling, 1 reply; 26+ messages in thread
From: Thomas Graf @ 2008-02-07 12:14 UTC (permalink / raw)
To: Patrick McHardy; +Cc: netfilter-devel, philipc
* Patrick McHardy <kaber@trash.net> 2008-01-18 17:55
> commit 5d2b826674d411f99e571fd35ad5722fed077e5e
> Author: Patrick McHardy <kaber@trash.net>
> Date: Fri Jan 18 17:53:14 2008 +0100
>
> [LIBNL]: Support conntrack add/delete/query requests
>
> Signed-off-by: Patrick McHardy <kaber@trash.net>
Applied, thanks everyone.
Will there be a src/nf-ct-(add|del|query).c? ;-)
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [LIBNL 08/09]: Support conntrack add/delete/query requests
2008-02-07 12:14 ` Thomas Graf
@ 2008-02-19 12:32 ` Patrick McHardy
0 siblings, 0 replies; 26+ messages in thread
From: Patrick McHardy @ 2008-02-19 12:32 UTC (permalink / raw)
To: Thomas Graf; +Cc: netfilter-devel, philipc
Thomas Graf wrote:
> * Patrick McHardy <kaber@trash.net> 2008-01-18 17:55
>> commit 5d2b826674d411f99e571fd35ad5722fed077e5e
>> Author: Patrick McHardy <kaber@trash.net>
>> Date: Fri Jan 18 17:53:14 2008 +0100
>>
>> [LIBNL]: Support conntrack add/delete/query requests
>>
>> Signed-off-by: Patrick McHardy <kaber@trash.net>
>
> Applied, thanks everyone.
>
> Will there be a src/nf-ct-(add|del|query).c? ;-)
I'll put one in when I find some time.
^ permalink raw reply [flat|nested] 26+ messages in thread
* [LIBNL 09/09]: Install netfilter headers
2008-01-18 16:55 [LIBNL 00/09]: Netfilter update + minor fixes Patrick McHardy
` (7 preceding siblings ...)
2008-01-18 16:55 ` [LIBNL 08/09]: Support conntrack add/delete/query requests Patrick McHardy
@ 2008-01-18 16:56 ` Patrick McHardy
2008-02-07 12:16 ` Thomas Graf
8 siblings, 1 reply; 26+ messages in thread
From: Patrick McHardy @ 2008-01-18 16:56 UTC (permalink / raw)
To: tgraf; +Cc: Patrick McHardy, netfilter-devel, philipc
commit 8c4229982c96650d5369fa33c40749de0ac29bb2
Author: Patrick McHardy <kaber@trash.net>
Date: Fri Jan 18 17:53:14 2008 +0100
[LIBNL]: Install netfilter headers
libnl currently forgets to install the netfilter headers.
Fix that.
Signed-off-by: Patrick McHardy <kaber@trash.net>
diff --git a/include/Makefile b/include/Makefile
index a2b23e0..968ebe5 100644
--- a/include/Makefile
+++ b/include/Makefile
@@ -29,10 +29,12 @@ install:
mkdir -p $(DESTDIR)$(includedir)/netlink/route/cls/
mkdir -p $(DESTDIR)$(includedir)/netlink/genl/
mkdir -p $(DESTDIR)$(includedir)/netlink/fib_lookup/
+ mkdir -p $(DESTDIR)$(includedir)/netlink/netfilter
install -m 0644 netlink/*.h $(DESTDIR)$(includedir)/netlink/
install -m 0644 netlink/route/*.h $(DESTDIR)$(includedir)/netlink/route/
install -m 0644 netlink/route/sch/*.h $(DESTDIR)$(includedir)/netlink/route/sch/
install -m 0644 netlink/route/cls/*.h $(DESTDIR)$(includedir)/netlink/route/cls/
install -m 0644 netlink/genl/*.h $(DESTDIR)$(includedir)/netlink/genl/
install -m 0644 netlink/fib_lookup/*.h $(DESTDIR)$(includedir)/netlink/fib_lookup/
+ install -m 0644 netlink/netfilter/*.h $(DESTDIR)$(includedir)/netlink/netfilter/
^ permalink raw reply related [flat|nested] 26+ messages in thread