--- a/arch/mips/include/asm/checksum.h +++ b/arch/mips/include/asm/checksum.h @@ -12,6 +12,7 @@ #define _ASM_CHECKSUM_H #include +#include #include @@ -104,26 +105,30 @@ static inline __sum16 ip_fast_csum(const const unsigned int *stop = word + ihl; unsigned int csum; int carry; + unsigned int w; - csum = word[0]; - csum += word[1]; - carry = (csum < word[1]); + csum = __get_unaligned_cpu32(word++); + + w = __get_unaligned_cpu32(word++); + csum += w; + carry = (csum < w); csum += carry; - csum += word[2]; - carry = (csum < word[2]); + w = __get_unaligned_cpu32(word++); + csum += w; + carry = (csum < w); csum += carry; - csum += word[3]; - carry = (csum < word[3]); + w = __get_unaligned_cpu32(word++); + csum += w; + carry = (csum < w); csum += carry; - word += 4; do { - csum += *word; - carry = (csum < *word); + w = __get_unaligned_cpu32(word++); + csum += w; + carry = (csum < w); csum += carry; - word++; } while (word != stop); return csum_fold(csum); --- a/include/uapi/linux/ip.h +++ b/include/uapi/linux/ip.h @@ -102,7 +102,7 @@ struct iphdr { __be32 saddr; __be32 daddr; /*The options start here. */ -}; +} __attribute__((packed, aligned(2))); struct ip_auth_hdr { --- a/include/uapi/linux/ipv6.h +++ b/include/uapi/linux/ipv6.h @@ -123,7 +123,7 @@ struct ipv6hdr { struct in6_addr saddr; struct in6_addr daddr; -}; +} __attribute__((packed, aligned(2))); /* index values for the variables in ipv6_devconf */ --- a/include/uapi/linux/tcp.h +++ b/include/uapi/linux/tcp.h @@ -54,7 +54,7 @@ struct tcphdr { __be16 window; __sum16 check; __be16 urg_ptr; -}; +} __attribute__((packed, aligned(2))); /* * The union cast uses a gcc extension to avoid aliasing problems @@ -64,7 +64,7 @@ struct tcphdr { union tcp_word_hdr { struct tcphdr hdr; __be32 words[5]; -}; +} __attribute__((packed, aligned(2))); #define tcp_flag_word(tp) ( ((union tcp_word_hdr *)(tp))->words [3]) --- a/include/uapi/linux/udp.h +++ b/include/uapi/linux/udp.h @@ -24,7 +24,7 @@ struct udphdr { __be16 dest; __be16 len; __sum16 check; -}; +} __attribute__((packed, aligned(2))); /* UDP socket options */ #define UDP_CORK 1 /* Never send partially complete segments */ --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -39,8 +40,8 @@ static bool ipv4_pkt_to_tuple(const stru if (ap == NULL) return false; - tuple->src.u3.ip = ap[0]; - tuple->dst.u3.ip = ap[1]; + tuple->src.u3.ip = __get_unaligned_cpu32(ap++); + tuple->dst.u3.ip = __get_unaligned_cpu32(ap); return true; } --- a/include/uapi/linux/icmp.h +++ b/include/uapi/linux/icmp.h @@ -80,7 +80,7 @@ struct icmphdr { __be16 mtu; } frag; } un; -}; +} __attribute__((packed, aligned(2))); /* --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3842,13 +3842,14 @@ static bool tcp_parse_aligned_timestamp( { const __be32 *ptr = (const __be32 *)(th + 1); - if (*ptr == htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) - | (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) { + if (__get_unaligned_cpu32(ptr) == + htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | + (TCPOPT_TIMESTAMP << 8) | TCPOLEN_TIMESTAMP)) { tp->rx_opt.saw_tstamp = 1; ++ptr; - tp->rx_opt.rcv_tsval = ntohl(*ptr); + tp->rx_opt.rcv_tsval = get_unaligned_be32(ptr); ++ptr; - tp->rx_opt.rcv_tsecr = ntohl(*ptr); + tp->rx_opt.rcv_tsecr = get_unaligned_be32(ptr); return true; } return false; --- a/include/uapi/linux/in6.h +++ b/include/uapi/linux/in6.h @@ -36,7 +36,7 @@ struct in6_addr { #define s6_addr in6_u.u6_addr8 #define s6_addr16 in6_u.u6_addr16 #define s6_addr32 in6_u.u6_addr32 -}; +} __attribute__((packed, aligned(2))); /* IPv6 Wildcard Address (::) and Loopback Address (::1) defined in RFC2553 * NOTE: Be aware the IN6ADDR_* constants and in6addr_* externals are defined --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -61,6 +61,7 @@ #endif #include +#include #include MODULE_AUTHOR("Cast of dozens"); @@ -880,7 +881,8 @@ static struct sk_buff **ipv6_gro_receive continue; iph2 = ipv6_hdr(p); - first_word = *(__be32 *)iph ^ *(__be32 *)iph2 ; + first_word = __get_unaligned_cpu32((__u32 *) iph) ^ + __get_unaligned_cpu32((__u32 *) iph2); /* All fields must match except length and Traffic Class. */ if (nlen != skb_network_header_len(p) ||