diff options
Diffstat (limited to 'net/appletalk/ddp.c')
-rw-r--r-- | net/appletalk/ddp.c | 79 |
1 files changed, 28 insertions, 51 deletions
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 | ||
1005 | static unsigned short atalk_checksum(const struct sk_buff *skb, int len) | 1005 | static __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 | ||
1016 | static struct proto ddp_proto = { | 1016 | static struct proto ddp_proto = { |
@@ -1289,7 +1289,7 @@ static int handle_ip_over_ddp(struct sk_buff *skb) | |||
1289 | #endif | 1289 | #endif |
1290 | 1290 | ||
1291 | static void atalk_route_packet(struct sk_buff *skb, struct net_device *dev, | 1291 | static 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) { |