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;