|
@@ -1234,27 +1234,27 @@ static int ipxitf_ioctl(unsigned int cmd, void __user *arg)
|
|
|
/* Note: We assume ipx_tctrl==0 and htons(length)==ipx_pktsize */
|
|
|
/* This functions should *not* mess with packet contents */
|
|
|
|
|
|
-__u16 ipx_cksum(struct ipxhdr *packet, int length)
|
|
|
+__be16 ipx_cksum(struct ipxhdr *packet, int length)
|
|
|
{
|
|
|
/*
|
|
|
* NOTE: sum is a net byte order quantity, which optimizes the
|
|
|
* loop. This only works on big and little endian machines. (I
|
|
|
* don't know of a machine that isn't.)
|
|
|
*/
|
|
|
- /* start at ipx_dest - We skip the checksum field and start with
|
|
|
- * ipx_type before the loop, not considering ipx_tctrl in the calc */
|
|
|
- __u16 *p = (__u16 *)&packet->ipx_dest;
|
|
|
- __u32 i = (length >> 1) - 1; /* Number of complete words */
|
|
|
- __u32 sum = packet->ipx_type << sizeof(packet->ipx_tctrl);
|
|
|
-
|
|
|
- /* Loop through all complete words except the checksum field,
|
|
|
- * ipx_type (accounted above) and ipx_tctrl (not used in the cksum) */
|
|
|
- while (--i)
|
|
|
+ /* handle the first 3 words separately; checksum should be skipped
|
|
|
+ * and ipx_tctrl masked out */
|
|
|
+ __u16 *p = (__u16 *)packet;
|
|
|
+ __u32 sum = p[1] + (p[2] & (__force u16)htons(0x00ff));
|
|
|
+ __u32 i = (length >> 1) - 3; /* Number of remaining complete words */
|
|
|
+
|
|
|
+ /* Loop through them */
|
|
|
+ p += 3;
|
|
|
+ while (i--)
|
|
|
sum += *p++;
|
|
|
|
|
|
/* Add on the last part word if it exists */
|
|
|
if (packet->ipx_pktsize & htons(1))
|
|
|
- sum += ntohs(0xff00) & *p;
|
|
|
+ sum += (__force u16)htons(0xff00) & *p;
|
|
|
|
|
|
/* Do final fixup */
|
|
|
sum = (sum & 0xffff) + (sum >> 16);
|
|
@@ -1263,7 +1263,14 @@ __u16 ipx_cksum(struct ipxhdr *packet, int length)
|
|
|
if (sum >= 0x10000)
|
|
|
sum++;
|
|
|
|
|
|
- return ~sum;
|
|
|
+ /*
|
|
|
+ * Leave 0 alone; we don't want 0xffff here. Note that we can't get
|
|
|
+ * here with 0x10000, so this check is the same as ((__u16)sum)
|
|
|
+ */
|
|
|
+ if (sum)
|
|
|
+ sum = ~sum;
|
|
|
+
|
|
|
+ return (__force __be16)sum;
|
|
|
}
|
|
|
|
|
|
const char *ipx_frame_name(__be16 frame)
|