aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/appletalk/ipddp.c5
-rw-r--r--include/linux/atalk.h40
-rw-r--r--net/appletalk/ddp.c79
3 files changed, 30 insertions, 94 deletions
diff --git a/drivers/net/appletalk/ipddp.c b/drivers/net/appletalk/ipddp.c
index 7f7dd450226a..b98592a8bac8 100644
--- a/drivers/net/appletalk/ipddp.c
+++ b/drivers/net/appletalk/ipddp.c
@@ -145,9 +145,7 @@ static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev)
145 145
146 /* Create the Extended DDP header */ 146 /* Create the Extended DDP header */
147 ddp = (struct ddpehdr *)skb->data; 147 ddp = (struct ddpehdr *)skb->data;
148 ddp->deh_len = skb->len; 148 ddp->deh_len_hops = htons(skb->len + (1<<10));
149 ddp->deh_hops = 1;
150 ddp->deh_pad = 0;
151 ddp->deh_sum = 0; 149 ddp->deh_sum = 0;
152 150
153 /* 151 /*
@@ -170,7 +168,6 @@ static int ipddp_xmit(struct sk_buff *skb, struct net_device *dev)
170 ddp->deh_sport = 72; 168 ddp->deh_sport = 72;
171 169
172 *((__u8 *)(ddp+1)) = 22; /* ddp type = IP */ 170 *((__u8 *)(ddp+1)) = 22; /* ddp type = IP */
173 *((__u16 *)ddp)=ntohs(*((__u16 *)ddp)); /* fix up length field */
174 171
175 skb->protocol = htons(ETH_P_ATALK); /* Protocol has changed */ 172 skb->protocol = htons(ETH_P_ATALK); /* Protocol has changed */
176 173
diff --git a/include/linux/atalk.h b/include/linux/atalk.h
index 6ba3aa8a81f4..75b8baca08f3 100644
--- a/include/linux/atalk.h
+++ b/include/linux/atalk.h
@@ -88,15 +88,7 @@ static inline struct atalk_sock *at_sk(struct sock *sk)
88#include <asm/byteorder.h> 88#include <asm/byteorder.h>
89 89
90struct ddpehdr { 90struct ddpehdr {
91#ifdef __LITTLE_ENDIAN_BITFIELD 91 __be16 deh_len_hops; /* lower 10 bits are length, next 4 - hops */
92 __u16 deh_len:10,
93 deh_hops:4,
94 deh_pad:2;
95#else
96 __u16 deh_pad:2,
97 deh_hops:4,
98 deh_len:10;
99#endif
100 __be16 deh_sum; 92 __be16 deh_sum;
101 __be16 deh_dnet; 93 __be16 deh_dnet;
102 __be16 deh_snet; 94 __be16 deh_snet;
@@ -112,36 +104,6 @@ static __inline__ struct ddpehdr *ddp_hdr(struct sk_buff *skb)
112 return (struct ddpehdr *)skb->h.raw; 104 return (struct ddpehdr *)skb->h.raw;
113} 105}
114 106
115/*
116 * Don't drop the struct into the struct above. You'll get some
117 * surprise padding.
118 */
119struct ddpebits {
120#ifdef __LITTLE_ENDIAN_BITFIELD
121 __u16 deh_len:10,
122 deh_hops:4,
123 deh_pad:2;
124#else
125 __u16 deh_pad:2,
126 deh_hops:4,
127 deh_len:10;
128#endif
129};
130
131/* Short form header */
132struct ddpshdr {
133#ifdef __LITTLE_ENDIAN_BITFIELD
134 __u16 dsh_len:10,
135 dsh_pad:6;
136#else
137 __u16 dsh_pad:6,
138 dsh_len:10;
139#endif
140 __u8 dsh_dport;
141 __u8 dsh_sport;
142 /* And netatalk apps expect to stick the type in themselves */
143};
144
145/* AppleTalk AARP headers */ 107/* AppleTalk AARP headers */
146struct elapaarp { 108struct elapaarp {
147 __be16 hw_type; 109 __be16 hw_type;
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 96dc6bb52d14..708e2e0371af 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -1002,7 +1002,7 @@ static unsigned long atalk_sum_skb(const struct sk_buff *skb, int offset,
1002 return sum; 1002 return sum;
1003} 1003}
1004 1004
1005static unsigned short atalk_checksum(const struct sk_buff *skb, int len) 1005static __be16 atalk_checksum(const struct sk_buff *skb, int len)
1006{ 1006{
1007 unsigned long sum; 1007 unsigned long sum;
1008 1008
@@ -1010,7 +1010,7 @@ static unsigned short atalk_checksum(const struct sk_buff *skb, int len)
1010 sum = atalk_sum_skb(skb, 4, len-4, 0); 1010 sum = atalk_sum_skb(skb, 4, len-4, 0);
1011 1011
1012 /* Use 0xFFFF for 0. 0 itself means none */ 1012 /* Use 0xFFFF for 0. 0 itself means none */
1013 return sum ? htons((unsigned short)sum) : 0xFFFF; 1013 return sum ? htons((unsigned short)sum) : htons(0xFFFF);
1014} 1014}
1015 1015
1016static struct proto ddp_proto = { 1016static struct proto ddp_proto = {
@@ -1289,7 +1289,7 @@ static int handle_ip_over_ddp(struct sk_buff *skb)
1289#endif 1289#endif
1290 1290
1291static void atalk_route_packet(struct sk_buff *skb, struct net_device *dev, 1291static void atalk_route_packet(struct sk_buff *skb, struct net_device *dev,
1292 struct ddpehdr *ddp, struct ddpebits *ddphv, 1292 struct ddpehdr *ddp, __u16 len_hops,
1293 int origlen) 1293 int origlen)
1294{ 1294{
1295 struct atalk_route *rt; 1295 struct atalk_route *rt;
@@ -1317,10 +1317,12 @@ static void atalk_route_packet(struct sk_buff *skb, struct net_device *dev,
1317 1317
1318 /* Route the packet */ 1318 /* Route the packet */
1319 rt = atrtr_find(&ta); 1319 rt = atrtr_find(&ta);
1320 if (!rt || ddphv->deh_hops == DDP_MAXHOPS) 1320 /* increment hops count */
1321 len_hops += 1 << 10;
1322 if (!rt || !(len_hops & (15 << 10)))
1321 goto free_it; 1323 goto free_it;
1324
1322 /* FIXME: use skb->cb to be able to use shared skbs */ 1325 /* FIXME: use skb->cb to be able to use shared skbs */
1323 ddphv->deh_hops++;
1324 1326
1325 /* 1327 /*
1326 * Route goes through another gateway, so set the target to the 1328 * 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,
1335 /* Fix up skb->len field */ 1337 /* Fix up skb->len field */
1336 skb_trim(skb, min_t(unsigned int, origlen, 1338 skb_trim(skb, min_t(unsigned int, origlen,
1337 (rt->dev->hard_header_len + 1339 (rt->dev->hard_header_len +
1338 ddp_dl->header_length + ddphv->deh_len))); 1340 ddp_dl->header_length + (len_hops & 1023))));
1339 1341
1340 /* Mend the byte order */
1341 /* FIXME: use skb->cb to be able to use shared skbs */ 1342 /* FIXME: use skb->cb to be able to use shared skbs */
1342 *((__u16 *)ddp) = ntohs(*((__u16 *)ddphv)); 1343 ddp->deh_len_hops = htons(len_hops);
1343 1344
1344 /* 1345 /*
1345 * Send the buffer onwards 1346 * Send the buffer onwards
@@ -1394,7 +1395,7 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
1394 struct atalk_iface *atif; 1395 struct atalk_iface *atif;
1395 struct sockaddr_at tosat; 1396 struct sockaddr_at tosat;
1396 int origlen; 1397 int origlen;
1397 struct ddpebits ddphv; 1398 __u16 len_hops;
1398 1399
1399 /* Don't mangle buffer if shared */ 1400 /* Don't mangle buffer if shared */
1400 if (!(skb = skb_share_check(skb, GFP_ATOMIC))) 1401 if (!(skb = skb_share_check(skb, GFP_ATOMIC)))
@@ -1406,16 +1407,11 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
1406 1407
1407 ddp = ddp_hdr(skb); 1408 ddp = ddp_hdr(skb);
1408 1409
1409 /* 1410 len_hops = ntohs(ddp->deh_len_hops);
1410 * Fix up the length field [Ok this is horrible but otherwise
1411 * I end up with unions of bit fields and messy bit field order
1412 * compiler/endian dependencies..]
1413 */
1414 *((__u16 *)&ddphv) = ntohs(*((__u16 *)ddp));
1415 1411
1416 /* Trim buffer in case of stray trailing data */ 1412 /* Trim buffer in case of stray trailing data */
1417 origlen = skb->len; 1413 origlen = skb->len;
1418 skb_trim(skb, min_t(unsigned int, skb->len, ddphv.deh_len)); 1414 skb_trim(skb, min_t(unsigned int, skb->len, len_hops & 1023));
1419 1415
1420 /* 1416 /*
1421 * Size check to see if ddp->deh_len was crap 1417 * 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,
1430 * valid for net byte orders all over the networking code... 1426 * valid for net byte orders all over the networking code...
1431 */ 1427 */
1432 if (ddp->deh_sum && 1428 if (ddp->deh_sum &&
1433 atalk_checksum(skb, ddphv.deh_len) != ddp->deh_sum) 1429 atalk_checksum(skb, len_hops & 1023) != ddp->deh_sum)
1434 /* Not a valid AppleTalk frame - dustbin time */ 1430 /* Not a valid AppleTalk frame - dustbin time */
1435 goto freeit; 1431 goto freeit;
1436 1432
@@ -1444,7 +1440,7 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
1444 /* Not ours, so we route the packet via the correct 1440 /* Not ours, so we route the packet via the correct
1445 * AppleTalk iface 1441 * AppleTalk iface
1446 */ 1442 */
1447 atalk_route_packet(skb, dev, ddp, &ddphv, origlen); 1443 atalk_route_packet(skb, dev, ddp, len_hops, origlen);
1448 goto out; 1444 goto out;
1449 } 1445 }
1450 1446
@@ -1489,7 +1485,7 @@ static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev,
1489 /* Find our address */ 1485 /* Find our address */
1490 struct atalk_addr *ap = atalk_find_dev_addr(dev); 1486 struct atalk_addr *ap = atalk_find_dev_addr(dev);
1491 1487
1492 if (!ap || skb->len < sizeof(struct ddpshdr)) 1488 if (!ap || skb->len < sizeof(__be16) || skb->len > 1023)
1493 goto freeit; 1489 goto freeit;
1494 1490
1495 /* Don't mangle buffer if shared */ 1491 /* Don't mangle buffer if shared */
@@ -1519,11 +1515,8 @@ static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev,
1519 /* 1515 /*
1520 * Not sure about this bit... 1516 * Not sure about this bit...
1521 */ 1517 */
1522 ddp->deh_len = skb->len; 1518 /* Non routable, so force a drop if we slip up later */
1523 ddp->deh_hops = DDP_MAXHOPS; /* Non routable, so force a drop 1519 ddp->deh_len_hops = htons(skb->len + (DDP_MAXHOPS << 10));
1524 if we slip up later */
1525 /* Mend the byte order */
1526 *((__u16 *)ddp) = htons(*((__u16 *)ddp));
1527 } 1520 }
1528 skb->h.raw = skb->data; 1521 skb->h.raw = skb->data;
1529 1522
@@ -1622,16 +1615,7 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
1622 SOCK_DEBUG(sk, "SK %p: Begin build.\n", sk); 1615 SOCK_DEBUG(sk, "SK %p: Begin build.\n", sk);
1623 1616
1624 ddp = (struct ddpehdr *)skb_put(skb, sizeof(struct ddpehdr)); 1617 ddp = (struct ddpehdr *)skb_put(skb, sizeof(struct ddpehdr));
1625 ddp->deh_pad = 0; 1618 ddp->deh_len_hops = htons(len + sizeof(*ddp));
1626 ddp->deh_hops = 0;
1627 ddp->deh_len = len + sizeof(*ddp);
1628 /*
1629 * Fix up the length field [Ok this is horrible but otherwise
1630 * I end up with unions of bit fields and messy bit field order
1631 * compiler/endian dependencies..
1632 */
1633 *((__u16 *)ddp) = ntohs(*((__u16 *)ddp));
1634
1635 ddp->deh_dnet = usat->sat_addr.s_net; 1619 ddp->deh_dnet = usat->sat_addr.s_net;
1636 ddp->deh_snet = at->src_net; 1620 ddp->deh_snet = at->src_net;
1637 ddp->deh_dnode = usat->sat_addr.s_node; 1621 ddp->deh_dnode = usat->sat_addr.s_node;
@@ -1712,8 +1696,8 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
1712 struct sockaddr_at *sat = (struct sockaddr_at *)msg->msg_name; 1696 struct sockaddr_at *sat = (struct sockaddr_at *)msg->msg_name;
1713 struct ddpehdr *ddp; 1697 struct ddpehdr *ddp;
1714 int copied = 0; 1698 int copied = 0;
1699 int offset = 0;
1715 int err = 0; 1700 int err = 0;
1716 struct ddpebits ddphv;
1717 struct sk_buff *skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, 1701 struct sk_buff *skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
1718 flags & MSG_DONTWAIT, &err); 1702 flags & MSG_DONTWAIT, &err);
1719 if (!skb) 1703 if (!skb)
@@ -1721,25 +1705,18 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
1721 1705
1722 /* FIXME: use skb->cb to be able to use shared skbs */ 1706 /* FIXME: use skb->cb to be able to use shared skbs */
1723 ddp = ddp_hdr(skb); 1707 ddp = ddp_hdr(skb);
1724 *((__u16 *)&ddphv) = ntohs(*((__u16 *)ddp)); 1708 copied = ntohs(ddp->deh_len_hops) & 1023;
1725 1709
1726 if (sk->sk_type == SOCK_RAW) { 1710 if (sk->sk_type != SOCK_RAW) {
1727 copied = ddphv.deh_len; 1711 offset = sizeof(*ddp);
1728 if (copied > size) { 1712 copied -= offset;
1729 copied = size; 1713 }
1730 msg->msg_flags |= MSG_TRUNC;
1731 }
1732 1714
1733 err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); 1715 if (copied > size) {
1734 } else { 1716 copied = size;
1735 copied = ddphv.deh_len - sizeof(*ddp); 1717 msg->msg_flags |= MSG_TRUNC;
1736 if (copied > size) {
1737 copied = size;
1738 msg->msg_flags |= MSG_TRUNC;
1739 }
1740 err = skb_copy_datagram_iovec(skb, sizeof(*ddp),
1741 msg->msg_iov, copied);
1742 } 1718 }
1719 err = skb_copy_datagram_iovec(skb, offset, msg->msg_iov, copied);
1743 1720
1744 if (!err) { 1721 if (!err) {
1745 if (sat) { 1722 if (sat) {