X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fipx%2Faf_ipx.c;h=8b0c25f74a43e1f59c301239c629fae54b183293;hb=987b0145d94eecf292d8b301228356f44611ab7c;hp=e6a50e82603b9290599295e4f9b6421229119af6;hpb=f7ed79d23a47594e7834d66a8f14449796d4f3e6;p=linux-2.6.git diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index e6a50e826..8b0c25f74 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -1235,27 +1235,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); @@ -1264,7 +1264,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(unsigned short frame) @@ -1643,14 +1650,17 @@ static int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL) goto out; - ipx = ipx_hdr(skb); - ipx_pktsize = ntohs(ipx->ipx_pktsize); + if (!pskb_may_pull(skb, sizeof(struct ipxhdr))) + goto drop; + + ipx_pktsize = ntohs(ipx_hdr(skb)->ipx_pktsize); /* Too small or invalid header? */ - if (ipx_pktsize < sizeof(struct ipxhdr) - || !pskb_may_pull(skb, ipx_pktsize)) + if (ipx_pktsize < sizeof(struct ipxhdr) || + !pskb_may_pull(skb, ipx_pktsize)) goto drop; + ipx = ipx_hdr(skb); if (ipx->ipx_checksum != IPX_NO_CHECKSUM && ipx->ipx_checksum != ipx_cksum(ipx, ipx_pktsize)) goto drop; @@ -1893,29 +1903,6 @@ static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) return rc; } - -#ifdef CONFIG_COMPAT -static int ipx_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) -{ - /* - * These 4 commands use same structure on 32bit and 64bit. Rest of IPX - * commands is handled by generic ioctl code. As these commands are - * SIOCPROTOPRIVATE..SIOCPROTOPRIVATE+3, they cannot be handled by generic - * code. - */ - switch (cmd) { - case SIOCAIPXITFCRT: - case SIOCAIPXPRISLT: - case SIOCIPXCFGDATA: - case SIOCIPXNCPCONN: - return ipx_ioctl(sock, cmd, arg); - default: - return -ENOIOCTLCMD; - } -} -#endif - - /* * Socket family declarations */ @@ -1937,9 +1924,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = { .getname = ipx_getname, .poll = datagram_poll, .ioctl = ipx_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = ipx_compat_ioctl, -#endif .listen = sock_no_listen, .shutdown = sock_no_shutdown, /* FIXME: support shutdown */ .setsockopt = ipx_setsockopt,