diff options
Diffstat (limited to 'net/appletalk/ddp.c')
| -rw-r--r-- | net/appletalk/ddp.c | 86 |
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) | |||
| 228 | static struct atalk_iface *atif_add_device(struct net_device *dev, | 227 | static 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 | ||
| 1008 | static unsigned short atalk_checksum(const struct sk_buff *skb, int len) | 1005 | static __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 | ||
| 1019 | static struct proto ddp_proto = { | 1016 | static struct proto ddp_proto = { |
| @@ -1292,7 +1289,7 @@ static int handle_ip_over_ddp(struct sk_buff *skb) | |||
| 1292 | #endif | 1289 | #endif |
| 1293 | 1290 | ||
| 1294 | 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, |
| 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) { |
