Hi,

Attached is a slightly less intrusive patch which avoids copying all
packet fields. I've confirmed that it correctly logs TCP/UDP/ICMP 
packets on sparc, it's also designed not to impact the performance on 
the platforms which do not have strong alignment requirements.

I would strongly suggest to rename the ipt_ULOG.h header shipped under
the debian/ directory to something like ipt_ULOG_local.h and modify 
the code appropriately, otherwise any error in setting up the include 
correctly during the build (Goswin noticed one of those) will result 
in the header being silently picked up from /usr/include. That's not 
what you want on sparc due to long/size_t size mismatch in kernel and 
userspace.

Best regards,  
-- 
Jurij Smakov                                           ju...@wooyd.org
Key: http://www.wooyd.org/pgpkey/                      KeyID: C99E03CC
diff -aur a/debian/include/linux/netfilter_ipv4/ipt_ULOG.h b/debian/include/linux/netfilter_ipv4/ipt_ULOG.h
--- a/debian/include/linux/netfilter_ipv4/ipt_ULOG.h	2010-04-08 22:18:47.000000000 +0100
+++ b/debian/include/linux/netfilter_ipv4/ipt_ULOG.h	2010-04-08 22:25:50.000000000 +0100
@@ -31,15 +31,28 @@
 	char prefix[ULOG_PREFIX_LEN];
 };
 
+/* This is needed to fix the mismatch between the field sizes in kernel
+ * and userspace. In particular, Debian sparc port features 32-bit
+ * userspace, but 64-bit kernel, leading to size mismatch. Structure
+ * above is not used anywhere in ulogd, otherwise it would need to be
+ * similarly mangled. */
+#ifdef __sparc__
+#define KERNEL_LONG long long
+#define KERNEL_SIZE_T unsigned long long
+#else
+#define KERNEL_LONG long
+#define KERNEL_SIZE_T size_t
+#endif
+
 /* Format of the ULOG packets passed through netlink */
 typedef struct ulog_packet_msg {
-	unsigned long mark;
-	long timestamp_sec;
-	long timestamp_usec;
+	unsigned KERNEL_LONG mark;
+	KERNEL_LONG timestamp_sec;
+	KERNEL_LONG timestamp_usec;
 	unsigned int hook;
 	char indev_name[IFNAMSIZ];
 	char outdev_name[IFNAMSIZ];
-	size_t data_len;
+	KERNEL_SIZE_T data_len;
 	char prefix[ULOG_PREFIX_LEN];
 	unsigned char mac_len;
 	unsigned char mac[ULOG_MAC_LEN];
diff -aur a/debian/patches/ipt_ULOG.patch b/debian/patches/ipt_ULOG.patch
--- a/debian/patches/ipt_ULOG.patch	2010-04-08 22:18:47.000000000 +0100
+++ b/debian/patches/ipt_ULOG.patch	2010-04-08 22:19:26.000000000 +0100
@@ -5,7 +5,7 @@
  # doesn't work for subdirs
  #CFLAGS+=$(INCIPULOG) $(INCCONFFILE)
 -CFLAGS+=-I/lib/modules/`uname -r`/build/include
-+cflags+...@srcdir@/debian/include
++CFLAGS+=-I$(PWD)/debian/include
  #cflag...@defs@
  #CFLAGS+=-g -DDEBUG -DDEBUG_MYSQL -DDEBUG_PGSQL
  
diff -aur a/extensions/ulogd_BASE.c b/extensions/ulogd_BASE.c
--- a/extensions/ulogd_BASE.c	2005-11-25 19:58:26.000000000 +0000
+++ b/extensions/ulogd_BASE.c	2010-04-08 22:18:35.000000000 +0100
@@ -203,7 +203,13 @@
 				ulog_packet_msg_t *pkt)
 {
 	ulog_iret_t *ret = ip->result;
+#ifdef STRICT_ALIGNMENT
+	struct iphdr aligned_iph;
+	memcpy(&aligned_iph, pkt->payload, sizeof(struct iphdr));
+	struct iphdr *iph = &aligned_iph;
+#else
 	struct iphdr *iph = (struct iphdr *) pkt->payload;
+#endif
 
 	ret[0].value.ui32 = ntohl(iph->saddr);
 	ret[0].flags |= ULOGD_RETF_VALID;
@@ -308,7 +314,13 @@
 {
 	struct iphdr *iph = (struct iphdr *) pkt->payload;
 	void *protoh = (u_int32_t *)iph + iph->ihl;
+#ifdef STRICT_ALIGNMENT
+	struct tcphdr aligned_tcph;
+	memcpy(&aligned_tcph, protoh, sizeof(struct tcphdr));
+	struct tcphdr *tcph = &aligned_tcph;
+#else
 	struct tcphdr *tcph = (struct tcphdr *) protoh;
+#endif
 	ulog_iret_t *ret = ip->result;
 
 	if (iph->protocol != IPPROTO_TCP)
@@ -382,7 +394,13 @@
 {
 	struct iphdr *iph = (struct iphdr *) pkt->payload;
 	void *protoh = (u_int32_t *)iph + iph->ihl;
-	struct udphdr *udph = protoh;
+#ifdef STRICT_ALIGNMENT
+	struct udphdr aligned_udph;
+	memcpy(&aligned_udph, protoh, sizeof(struct udphdr));
+	struct udphdr *udph = &aligned_udph;
+#else
+	struct udphdr *udph = (struct udphdr *) protoh;
+#endif
 	ulog_iret_t *ret = ip->result;
 
 	if (iph->protocol != IPPROTO_UDP)
@@ -440,7 +458,13 @@
 {
 	struct iphdr *iph = (struct iphdr *) pkt->payload;
 	void *protoh = (u_int32_t *)iph + iph->ihl;
-	struct icmphdr *icmph = protoh;
+#ifdef STRICT_ALIGNMENT
+	struct icmphdr aligned_icmph;
+	memcpy(&aligned_icmph, protoh, sizeof(struct icmphdr));
+	struct icmphdr *icmph = &aligned_icmph;
+#else
+	struct icmphdr *icmph = (struct icmphdr *) protoh;
+#endif
 	ulog_iret_t *ret = ip->result;
 
 	if (iph->protocol != IPPROTO_ICMP)
diff -aur a/extensions/ulogd_PWSNIFF.c b/extensions/ulogd_PWSNIFF.c
--- a/extensions/ulogd_PWSNIFF.c	2005-11-25 19:58:26.000000000 +0000
+++ b/extensions/ulogd_PWSNIFF.c	2010-04-08 22:16:43.000000000 +0100
@@ -64,7 +64,13 @@
 
 static ulog_iret_t *_interp_pwsniff(ulog_interpreter_t *ip, ulog_packet_msg_t *pkt)
 {
+#ifdef STRICT_ALIGNMENT
+	char aligned_payload[sizeof(struct iphdr) + sizeof(struct tcphdr)];
+	memcpy(aligned_payload, pkt->payload, sizeof(struct iphdr) + sizeof(struct tcphdr));
+	struct iphdr *iph = (struct iphdr *) aligned_payload;
+#else
 	struct iphdr *iph = (struct iphdr *) pkt->payload;
+#endif
 	void *protoh = (u_int32_t *)iph + iph->ihl;
 	struct tcphdr *tcph = protoh;
 	u_int32_t tcplen = ntohs(iph->tot_len) - iph->ihl * 4;
diff -aur a/include/ulogd/ulogd.h b/include/ulogd/ulogd.h
--- a/include/ulogd/ulogd.h	2005-11-25 19:58:25.000000000 +0000
+++ b/include/ulogd/ulogd.h	2010-04-08 21:49:22.000000000 +0100
@@ -56,6 +56,12 @@
 #define ULOGD_ERROR	7	/* error condition, requires user action */
 #define ULOGD_FATAL	8	/* fatal, program aborted */
 
+
+/* whether the platform has strict alignment requirements */
+#ifdef __sparc__
+#define STRICT_ALIGNMENT
+#endif
+
 typedef struct ulog_iret {
 	/* next interpreter return (key) in the global list */
 	struct ulog_iret *next;

Reply via email to