aboutsummaryrefslogtreecommitdiffstats
path: root/net/appletalk/ddp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/appletalk/ddp.c')
-rw-r--r--net/appletalk/ddp.c86
1 files changed, 30 insertions, 56 deletions
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 7b1eb9a4fc96..708e2e0371af 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -51,7 +51,6 @@
51 * 51 *
52 */ 52 */
53 53
54#include <linux/config.h>
55#include <linux/capability.h> 54#include <linux/capability.h>
56#include <linux/module.h> 55#include <linux/module.h>
57#include <linux/if_arp.h> 56#include <linux/if_arp.h>
@@ -228,12 +227,11 @@ static void atif_drop_device(struct net_device *dev)
228static struct atalk_iface *atif_add_device(struct net_device *dev, 227static struct atalk_iface *atif_add_device(struct net_device *dev,
229 struct atalk_addr *sa) 228 struct atalk_addr *sa)
230{ 229{
231 struct atalk_iface *iface = kmalloc(sizeof(*iface), GFP_KERNEL); 230 struct atalk_iface *iface = kzalloc(sizeof(*iface), GFP_KERNEL);
232 231
233 if (!iface) 232 if (!iface)
234 goto out; 233 goto out;
235 234
236 memset(iface, 0, sizeof(*iface));
237 dev_hold(dev); 235 dev_hold(dev);
238 iface->dev = dev; 236 iface->dev = dev;
239 dev->atalk_ptr = iface; 237 dev->atalk_ptr = iface;
@@ -560,12 +558,11 @@ static int atrtr_create(struct rtentry *r, struct net_device *devhint)
560 } 558 }
561 559
562 if (!rt) { 560 if (!rt) {
563 rt = kmalloc(sizeof(*rt), GFP_ATOMIC); 561 rt = kzalloc(sizeof(*rt), GFP_ATOMIC);
564 562
565 retval = -ENOBUFS; 563 retval = -ENOBUFS;
566 if (!rt) 564 if (!rt)
567 goto out_unlock; 565 goto out_unlock;
568 memset(rt, 0, sizeof(*rt));
569 566
570 rt->next = atalk_routes; 567 rt->next = atalk_routes;
571 atalk_routes = rt; 568 atalk_routes = rt;
@@ -1005,7 +1002,7 @@ static unsigned long atalk_sum_skb(const struct sk_buff *skb, int offset,
1005 return sum; 1002 return sum;
1006} 1003}
1007 1004
1008static unsigned short atalk_checksum(const struct sk_buff *skb, int len) 1005static __be16 atalk_checksum(const struct sk_buff *skb, int len)
1009{ 1006{
1010 unsigned long sum; 1007 unsigned long sum;
1011 1008
@@ -1013,7 +1010,7 @@ static unsigned short atalk_checksum(const struct sk_buff *skb, int len)
1013 sum = atalk_sum_skb(skb, 4, len-4, 0); 1010 sum = atalk_sum_skb(skb, 4, len-4, 0);
1014 1011
1015 /* Use 0xFFFF for 0. 0 itself means none */ 1012 /* Use 0xFFFF for 0. 0 itself means none */
1016 return sum ? htons((unsigned short)sum) : 0xFFFF; 1013 return sum ? htons((unsigned short)sum) : htons(0xFFFF);
1017} 1014}
1018 1015
1019static struct proto ddp_proto = { 1016static struct proto ddp_proto = {
@@ -1292,7 +1289,7 @@ static int handle_ip_over_ddp(struct sk_buff *skb)
1292#endif 1289#endif
1293 1290
1294static 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,
1295 struct ddpehdr *ddp, struct ddpebits *ddphv, 1292 struct ddpehdr *ddp, __u16 len_hops,
1296 int origlen) 1293 int origlen)
1297{ 1294{
1298 struct atalk_route *rt; 1295 struct atalk_route *rt;
@@ -1320,10 +1317,12 @@ static void atalk_route_packet(struct sk_buff *skb, struct net_device *dev,
1320 1317
1321 /* Route the packet */ 1318 /* Route the packet */
1322 rt = atrtr_find(&ta); 1319 rt = atrtr_find(&ta);
1323 if (!rt || ddphv->deh_hops == DDP_MAXHOPS) 1320 /* increment hops count */
1321 len_hops += 1 << 10;
1322 if (!rt || !(len_hops & (15 << 10)))
1324 goto free_it; 1323 goto free_it;
1324
1325 /* FIXME: use skb->cb to be able to use shared skbs */ 1325 /* FIXME: use skb->cb to be able to use shared skbs */
1326 ddphv->deh_hops++;
1327 1326
1328 /* 1327 /*
1329 * Route goes through another gateway, so set the target to the 1328 * Route goes through another gateway, so set the target to the
@@ -1338,11 +1337,10 @@ static void atalk_route_packet(struct sk_buff *skb, struct net_device *dev,
1338 /* Fix up skb->len field */ 1337 /* Fix up skb->len field */
1339 skb_trim(skb, min_t(unsigned int, origlen, 1338 skb_trim(skb, min_t(unsigned int, origlen,
1340 (rt->dev->hard_header_len + 1339 (rt->dev->hard_header_len +
1341 ddp_dl->header_length + ddphv->deh_len))); 1340 ddp_dl->header_length + (len_hops & 1023))));
1342 1341
1343 /* Mend the byte order */
1344 /* FIXME: use skb->cb to be able to use shared skbs */ 1342 /* FIXME: use skb->cb to be able to use shared skbs */
1345 *((__u16 *)ddp) = ntohs(*((__u16 *)ddphv)); 1343 ddp->deh_len_hops = htons(len_hops);
1346 1344
1347 /* 1345 /*
1348 * Send the buffer onwards 1346 * Send the buffer onwards
@@ -1397,7 +1395,7 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
1397 struct atalk_iface *atif; 1395 struct atalk_iface *atif;
1398 struct sockaddr_at tosat; 1396 struct sockaddr_at tosat;
1399 int origlen; 1397 int origlen;
1400 struct ddpebits ddphv; 1398 __u16 len_hops;
1401 1399
1402 /* Don't mangle buffer if shared */ 1400 /* Don't mangle buffer if shared */
1403 if (!(skb = skb_share_check(skb, GFP_ATOMIC))) 1401 if (!(skb = skb_share_check(skb, GFP_ATOMIC)))
@@ -1409,16 +1407,11 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
1409 1407
1410 ddp = ddp_hdr(skb); 1408 ddp = ddp_hdr(skb);
1411 1409
1412 /* 1410 len_hops = ntohs(ddp->deh_len_hops);
1413 * Fix up the length field [Ok this is horrible but otherwise
1414 * I end up with unions of bit fields and messy bit field order
1415 * compiler/endian dependencies..]
1416 */
1417 *((__u16 *)&ddphv) = ntohs(*((__u16 *)ddp));
1418 1411
1419 /* Trim buffer in case of stray trailing data */ 1412 /* Trim buffer in case of stray trailing data */
1420 origlen = skb->len; 1413 origlen = skb->len;
1421 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));
1422 1415
1423 /* 1416 /*
1424 * Size check to see if ddp->deh_len was crap 1417 * Size check to see if ddp->deh_len was crap
@@ -1433,7 +1426,7 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
1433 * valid for net byte orders all over the networking code... 1426 * valid for net byte orders all over the networking code...
1434 */ 1427 */
1435 if (ddp->deh_sum && 1428 if (ddp->deh_sum &&
1436 atalk_checksum(skb, ddphv.deh_len) != ddp->deh_sum) 1429 atalk_checksum(skb, len_hops & 1023) != ddp->deh_sum)
1437 /* Not a valid AppleTalk frame - dustbin time */ 1430 /* Not a valid AppleTalk frame - dustbin time */
1438 goto freeit; 1431 goto freeit;
1439 1432
@@ -1447,7 +1440,7 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
1447 /* Not ours, so we route the packet via the correct 1440 /* Not ours, so we route the packet via the correct
1448 * AppleTalk iface 1441 * AppleTalk iface
1449 */ 1442 */
1450 atalk_route_packet(skb, dev, ddp, &ddphv, origlen); 1443 atalk_route_packet(skb, dev, ddp, len_hops, origlen);
1451 goto out; 1444 goto out;
1452 } 1445 }
1453 1446
@@ -1492,7 +1485,7 @@ static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev,
1492 /* Find our address */ 1485 /* Find our address */
1493 struct atalk_addr *ap = atalk_find_dev_addr(dev); 1486 struct atalk_addr *ap = atalk_find_dev_addr(dev);
1494 1487
1495 if (!ap || skb->len < sizeof(struct ddpshdr)) 1488 if (!ap || skb->len < sizeof(__be16) || skb->len > 1023)
1496 goto freeit; 1489 goto freeit;
1497 1490
1498 /* Don't mangle buffer if shared */ 1491 /* Don't mangle buffer if shared */
@@ -1522,11 +1515,8 @@ static int ltalk_rcv(struct sk_buff *skb, struct net_device *dev,
1522 /* 1515 /*
1523 * Not sure about this bit... 1516 * Not sure about this bit...
1524 */ 1517 */
1525 ddp->deh_len = skb->len; 1518 /* Non routable, so force a drop if we slip up later */
1526 ddp->deh_hops = DDP_MAXHOPS; /* Non routable, so force a drop 1519 ddp->deh_len_hops = htons(skb->len + (DDP_MAXHOPS << 10));
1527 if we slip up later */
1528 /* Mend the byte order */
1529 *((__u16 *)ddp) = htons(*((__u16 *)ddp));
1530 } 1520 }
1531 skb->h.raw = skb->data; 1521 skb->h.raw = skb->data;
1532 1522
@@ -1625,16 +1615,7 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
1625 SOCK_DEBUG(sk, "SK %p: Begin build.\n", sk); 1615 SOCK_DEBUG(sk, "SK %p: Begin build.\n", sk);
1626 1616
1627 ddp = (struct ddpehdr *)skb_put(skb, sizeof(struct ddpehdr)); 1617 ddp = (struct ddpehdr *)skb_put(skb, sizeof(struct ddpehdr));
1628 ddp->deh_pad = 0; 1618 ddp->deh_len_hops = htons(len + sizeof(*ddp));
1629 ddp->deh_hops = 0;
1630 ddp->deh_len = len + sizeof(*ddp);
1631 /*
1632 * Fix up the length field [Ok this is horrible but otherwise
1633 * I end up with unions of bit fields and messy bit field order
1634 * compiler/endian dependencies..
1635 */
1636 *((__u16 *)ddp) = ntohs(*((__u16 *)ddp));
1637
1638 ddp->deh_dnet = usat->sat_addr.s_net; 1619 ddp->deh_dnet = usat->sat_addr.s_net;
1639 ddp->deh_snet = at->src_net; 1620 ddp->deh_snet = at->src_net;
1640 ddp->deh_dnode = usat->sat_addr.s_node; 1621 ddp->deh_dnode = usat->sat_addr.s_node;
@@ -1715,8 +1696,8 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
1715 struct sockaddr_at *sat = (struct sockaddr_at *)msg->msg_name; 1696 struct sockaddr_at *sat = (struct sockaddr_at *)msg->msg_name;
1716 struct ddpehdr *ddp; 1697 struct ddpehdr *ddp;
1717 int copied = 0; 1698 int copied = 0;
1699 int offset = 0;
1718 int err = 0; 1700 int err = 0;
1719 struct ddpebits ddphv;
1720 struct sk_buff *skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, 1701 struct sk_buff *skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
1721 flags & MSG_DONTWAIT, &err); 1702 flags & MSG_DONTWAIT, &err);
1722 if (!skb) 1703 if (!skb)
@@ -1724,25 +1705,18 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
1724 1705
1725 /* FIXME: use skb->cb to be able to use shared skbs */ 1706 /* FIXME: use skb->cb to be able to use shared skbs */
1726 ddp = ddp_hdr(skb); 1707 ddp = ddp_hdr(skb);
1727 *((__u16 *)&ddphv) = ntohs(*((__u16 *)ddp)); 1708 copied = ntohs(ddp->deh_len_hops) & 1023;
1728 1709
1729 if (sk->sk_type == SOCK_RAW) { 1710 if (sk->sk_type != SOCK_RAW) {
1730 copied = ddphv.deh_len; 1711 offset = sizeof(*ddp);
1731 if (copied > size) { 1712 copied -= offset;
1732 copied = size; 1713 }
1733 msg->msg_flags |= MSG_TRUNC;
1734 }
1735 1714
1736 err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); 1715 if (copied > size) {
1737 } else { 1716 copied = size;
1738 copied = ddphv.deh_len - sizeof(*ddp); 1717 msg->msg_flags |= MSG_TRUNC;
1739 if (copied > size) {
1740 copied = size;
1741 msg->msg_flags |= MSG_TRUNC;
1742 }
1743 err = skb_copy_datagram_iovec(skb, sizeof(*ddp),
1744 msg->msg_iov, copied);
1745 } 1718 }
1719 err = skb_copy_datagram_iovec(skb, offset, msg->msg_iov, copied);
1746 1720
1747 if (!err) { 1721 if (!err) {
1748 if (sat) { 1722 if (sat) {