|
|
|
--- a/arch/mips/include/asm/checksum.h
|
|
|
|
+++ b/arch/mips/include/asm/checksum.h
|
|
|
|
@@ -12,6 +12,7 @@
|
|
|
|
#define _ASM_CHECKSUM_H
|
|
|
|
|
|
|
|
#include <linux/in6.h>
|
|
|
|
+#include <linux/unaligned/packed_struct.h>
|
|
|
|
|
|
|
|
#include <asm/uaccess.h>
|
|
|
|
|
|
|
|
@@ -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 <linux/skbuff.h>
|
|
|
|
#include <linux/icmp.h>
|
|
|
|
#include <linux/sysctl.h>
|
|
|
|
+#include <linux/unaligned/packed_struct.h>
|
|
|
|
#include <net/route.h>
|
|
|
|
#include <net/ip.h>
|
|
|
|
|
|
|
|
@@ -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 <asm/uaccess.h>
|
|
|
|
+#include <asm/unaligned.h>
|
|
|
|
#include <linux/mroute6.h>
|
|
|
|
|
|
|
|
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) ||
|