[ATALK]: endianness annotations
authorAl Viro <viro@zeniv.linux.org.uk>
Wed, 27 Sep 2006 04:22:08 +0000 (21:22 -0700)
committerDavid S. Miller <davem@sunset.davemloft.net>
Fri, 29 Sep 2006 00:53:58 +0000 (17:53 -0700)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/appletalk/ipddp.c
include/linux/atalk.h
net/appletalk/ddp.c

index 7f7dd45..b98592a 100644 (file)
@@ -145,9 +145,7 @@ static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev)
 
        /* Create the Extended DDP header */
        ddp = (struct ddpehdr *)skb->data;
-        ddp->deh_len = skb->len;
-        ddp->deh_hops = 1;
-        ddp->deh_pad = 0;
+        ddp->deh_len_hops = htons(skb->len + (1<<10));
         ddp->deh_sum = 0;
 
        /*
@@ -170,7 +168,6 @@ static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev)
         ddp->deh_sport = 72;
 
         *((__u8 *)(ddp+1)) = 22;               /* ddp type = IP */
-        *((__u16 *)ddp)=ntohs(*((__u16 *)ddp));        /* fix up length field */
 
         skb->protocol = htons(ETH_P_ATALK);     /* Protocol has changed */
 
index 6ba3aa8..75b8bac 100644 (file)
@@ -88,15 +88,7 @@ static inline struct atalk_sock *at_sk(struct sock *sk)
 #include <asm/byteorder.h>
 
 struct ddpehdr {
-#ifdef __LITTLE_ENDIAN_BITFIELD
-       __u16   deh_len:10,
-               deh_hops:4,
-               deh_pad:2;
-#else
-       __u16   deh_pad:2,
-               deh_hops:4,
-               deh_len:10;
-#endif
+       __be16  deh_len_hops;   /* lower 10 bits are length, next 4 - hops */
        __be16  deh_sum;
        __be16  deh_dnet;
        __be16  deh_snet;
@@ -112,36 +104,6 @@ static __inline__ struct ddpehdr *ddp_hdr(struct sk_buff *skb)
        return (struct ddpehdr *)skb->h.raw;
 }
 
-/*
- *     Don't drop the struct into the struct above.  You'll get some
- *     surprise padding.
- */
-struct ddpebits {
-#ifdef __LITTLE_ENDIAN_BITFIELD
-       __u16   deh_len:10,
-               deh_hops:4,
-               deh_pad:2;
-#else
-       __u16   deh_pad:2,
-               deh_hops:4,
-               deh_len:10;
-#endif
-};
-
-/* Short form header */
-struct ddpshdr {
-#ifdef __LITTLE_ENDIAN_BITFIELD
-       __u16   dsh_len:10,
-               dsh_pad:6;
-#else
-       __u16   dsh_pad:6,
-               dsh_len:10;
-#endif
-       __u8    dsh_dport;
-       __u8    dsh_sport;
-       /* And netatalk apps expect to stick the type in themselves */
-};
-
 /* AppleTalk AARP headers */
 struct elapaarp {
        __be16  hw_type;
index 96dc6bb..708e2e0 100644 (file)
@@ -1002,7 +1002,7 @@ static unsigned long atalk_sum_skb(const struct sk_buff *skb, int offset,
        return sum;
 }
 
-static unsigned short atalk_checksum(const struct sk_buff *skb, int len)
+static __be16 atalk_checksum(const struct sk_buff *skb, int len)
 {
        unsigned long sum;
 
@@ -1010,7 +1010,7 @@ static unsigned short atalk_checksum(const struct sk_buff *skb, int len)
        sum = atalk_sum_skb(skb, 4, len-4, 0);
 
        /* Use 0xFFFF for 0. 0 itself means none */
-       return sum ? htons((unsigned short)sum) : 0xFFFF;
+       return sum ? htons((unsigned short)sum) : htons(0xFFFF);
 }
 
 static struct proto ddp_proto = {
@@ -1289,7 +1289,7 @@ static int handle_ip_over_ddp(struct sk_buff *skb)
 #endif
 
 static void atalk_route_packet(struct sk_buff *skb, struct net_device *dev,
-                              struct ddpehdr *ddp, struct ddpebits *ddphv,
+                              struct ddpehdr *ddp, __u16 len_hops,
                               int origlen)
 {
        struct atalk_route *rt;
@@ -1317,10 +1317,12 @@ static void atalk_route_packet(struct sk_buff *skb, struct net_device *dev,
 
        /* Route the packet */
        rt = atrtr_find(&ta);
-       if (!rt || ddphv->deh_hops == DDP_MAXHOPS)
+       /* increment hops count */
+       len_hops += 1 << 10;
+       if (!rt || !(len_hops & (15 << 10)))
                goto free_it;
+
        /* FIXME: use skb->cb to be able to use shared skbs */
-       ddphv->deh_hops++;
 
        /*
         * Route goes through another gateway, so set the target to the
@@ -1335,11 +1337,10 @@ static void atalk_route_packet(struct sk_buff *skb, struct net_device *dev,
         /* Fix up skb->len field */
         skb_trim(skb, min_t(unsigned int, origlen,
                            (rt->dev->hard_header_len +
-                            ddp_dl->header_length + ddphv->deh_len)));
+                            ddp_dl->header_length + (len_hops & 1023))));
 
-       /* Mend the byte order */
        /* FIXME: use skb->cb to be able to use shared skbs */
-       *((__u16 *)ddp) = ntohs(*((__u16 *)ddphv));
+       ddp->deh_len_hops = htons(len_hops);
 
        /*
         * Send the buffer onwards
@@ -1394,7 +1395,7 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
        struct atalk_iface *atif;
        struct sockaddr_at tosat;
         int origlen;
-        struct ddpebits ddphv;
+       __u16 len_hops;
 
        /* Don't mangle buffer if shared */
        if (!(skb = skb_share_check(skb, GFP_ATOMIC))) 
@@ -1406,16 +1407,11 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
 
        ddp = ddp_hdr(skb);
 
-       /*
-        *      Fix up the length field [Ok this is horrible but otherwise
-        *      I end up with unions of bit fields and messy bit field order
-        *      compiler/endian dependencies..]
-        */
-       *((__u16 *)&ddphv) = ntohs(*((__u16 *)ddp));
+       len_hops = ntohs(ddp->deh_len_hops);
 
        /* Trim buffer in case of stray trailing data */
        origlen = skb->len;
-       skb_trim(skb, min_t(unsigned int, skb->len, ddphv.deh_len));
+       skb_trim(skb, min_t(unsigned int, skb->len, len_hops & 1023));
 
        /*
         * Size check to see if ddp->deh_len was crap
@@ -1430,7 +1426,7 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
         * valid for net byte orders all over the networking code...
         */
        if (ddp->deh_sum &&
-           atalk_checksum(skb, ddphv.deh_len) != ddp->deh_sum)
+           atalk_checksum(skb, len_hops & 1023) != ddp->deh_sum)
                /* Not a valid AppleTalk frame - dustbin time */
                goto freeit;
 
@@ -1444,7 +1440,7 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
                /* Not ours, so we route the packet via the correct
                 * AppleTalk iface
                 */
-               atalk_route_packet(skb, dev, ddp, &ddphv, origlen);
+               atalk_route_packet(skb, dev, ddp, len_hops, origlen);
                goto out;
        }
 
@@ -1489,7 +1485,7 @@ static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev,
                /* Find our address */
                struct atalk_addr *ap = atalk_find_dev_addr(dev);
 
-               if (!ap || skb->len < sizeof(struct ddpshdr))
+               if (!ap || skb->len < sizeof(__be16) || skb->len > 1023)
                        goto freeit;
 
                /* Don't mangle buffer if shared */
@@ -1519,11 +1515,8 @@ static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev,
                /*
                 * Not sure about this bit...
                 */
-               ddp->deh_len   = skb->len;
-               ddp->deh_hops  = DDP_MAXHOPS;   /* Non routable, so force a drop
-                                                  if we slip up later */
-               /* Mend the byte order */
-               *((__u16 *)ddp) = htons(*((__u16 *)ddp));
+               /* Non routable, so force a drop if we slip up later */
+               ddp->deh_len_hops = htons(skb->len + (DDP_MAXHOPS << 10));
        }
        skb->h.raw = skb->data;
 
@@ -1622,16 +1615,7 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
        SOCK_DEBUG(sk, "SK %p: Begin build.\n", sk);
 
        ddp = (struct ddpehdr *)skb_put(skb, sizeof(struct ddpehdr));
-       ddp->deh_pad  = 0;
-       ddp->deh_hops = 0;
-       ddp->deh_len  = len + sizeof(*ddp);
-       /*
-        * Fix up the length field [Ok this is horrible but otherwise
-        * I end up with unions of bit fields and messy bit field order
-        * compiler/endian dependencies..
-        */
-       *((__u16 *)ddp) = ntohs(*((__u16 *)ddp));
-
+       ddp->deh_len_hops  = htons(len + sizeof(*ddp));
        ddp->deh_dnet  = usat->sat_addr.s_net;
        ddp->deh_snet  = at->src_net;
        ddp->deh_dnode = usat->sat_addr.s_node;
@@ -1712,8 +1696,8 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
        struct sockaddr_at *sat = (struct sockaddr_at *)msg->msg_name;
        struct ddpehdr *ddp;
        int copied = 0;
+       int offset = 0;
        int err = 0;
-        struct ddpebits ddphv;
        struct sk_buff *skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
                                                flags & MSG_DONTWAIT, &err);
        if (!skb)
@@ -1721,25 +1705,18 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
 
        /* FIXME: use skb->cb to be able to use shared skbs */
        ddp = ddp_hdr(skb);
-       *((__u16 *)&ddphv) = ntohs(*((__u16 *)ddp));
+       copied = ntohs(ddp->deh_len_hops) & 1023;
 
-       if (sk->sk_type == SOCK_RAW) {
-               copied = ddphv.deh_len;
-               if (copied > size) {
-                       copied = size;
-                       msg->msg_flags |= MSG_TRUNC;
-               }
+       if (sk->sk_type != SOCK_RAW) {
+               offset = sizeof(*ddp);
+               copied -= offset;
+       }
 
-               err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
-       } else {
-               copied = ddphv.deh_len - sizeof(*ddp);
-               if (copied > size) {
-                       copied = size;
-                       msg->msg_flags |= MSG_TRUNC;
-               }
-               err = skb_copy_datagram_iovec(skb, sizeof(*ddp),
-                                             msg->msg_iov, copied);
+       if (copied > size) {
+               copied = size;
+               msg->msg_flags |= MSG_TRUNC;
        }
+       err = skb_copy_datagram_iovec(skb, offset, msg->msg_iov, copied);
 
        if (!err) {
                if (sat) {