Commit 64233bffbb50f12e576c61d1698a573c8033004a
Committed by
David S. Miller
1 parent
ba645c1602
Exists in
master
and in
39 other branches
[APPLETALK]: Fix broadcast bug.
From: Oliver Dawid <oliver@helios.de> we found a bug in net/appletalk/ddp.c concerning broadcast packets. In kernel 2.4 it was working fine. The bug first occured 4 years ago when switching to new SNAP layer handling. This bug can be splitted up into a sending(1) and reception(2) problem: Sending(1) In kernel 2.4 broadcast packets were sent to a matching ethernet device and atalk_rcv() was called to receive it as "loopback" (so loopback packets were shortcutted and handled in DDP layer). When switching to the new SNAP structure, this shortcut was removed and the loopback packet was send to SNAP layer. The author forgot to replace the remote device pointer by the loopback device pointer before sending the packet to SNAP layer (by calling ddp_dl->request() ) therfor the packet was not sent back by underlying layers to ddp's atalk_rcv(). Reception(2) In atalk_rcv() a packet received by this loopback mechanism contains now the (rigth) loopback device pointer (in Kernel 2.4 it was the (wrong) remote ethernet device pointer) and therefor no matching socket will be found to deliver this packet to. Because a broadcast packet should be send to the first matching socket (as it is done in many other protocols (?)), we removed the network comparison in broadcast case. Below you will find a patch to correct this bug. Its diffed to kernel 2.6.14-rc1 Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 1 changed file with 22 additions and 9 deletions Side-by-side Diff
net/appletalk/ddp.c
... | ... | @@ -100,8 +100,7 @@ |
100 | 100 | continue; |
101 | 101 | |
102 | 102 | if (to->sat_addr.s_net == ATADDR_ANYNET && |
103 | - to->sat_addr.s_node == ATADDR_BCAST && | |
104 | - at->src_net == atif->address.s_net) | |
103 | + to->sat_addr.s_node == ATADDR_BCAST) | |
105 | 104 | goto found; |
106 | 105 | |
107 | 106 | if (to->sat_addr.s_net == at->src_net && |
108 | 107 | |
... | ... | @@ -1443,8 +1442,10 @@ |
1443 | 1442 | else |
1444 | 1443 | atif = atalk_find_interface(ddp->deh_dnet, ddp->deh_dnode); |
1445 | 1444 | |
1446 | - /* Not ours, so we route the packet via the correct AppleTalk iface */ | |
1447 | 1445 | if (!atif) { |
1446 | + /* Not ours, so we route the packet via the correct | |
1447 | + * AppleTalk iface | |
1448 | + */ | |
1448 | 1449 | atalk_route_packet(skb, dev, ddp, &ddphv, origlen); |
1449 | 1450 | goto out; |
1450 | 1451 | } |
... | ... | @@ -1592,9 +1593,6 @@ |
1592 | 1593 | |
1593 | 1594 | if (usat->sat_addr.s_net || usat->sat_addr.s_node == ATADDR_ANYNODE) { |
1594 | 1595 | rt = atrtr_find(&usat->sat_addr); |
1595 | - if (!rt) | |
1596 | - return -ENETUNREACH; | |
1597 | - | |
1598 | 1596 | dev = rt->dev; |
1599 | 1597 | } else { |
1600 | 1598 | struct atalk_addr at_hint; |
1601 | 1599 | |
1602 | 1600 | |
... | ... | @@ -1603,12 +1601,13 @@ |
1603 | 1601 | at_hint.s_net = at->src_net; |
1604 | 1602 | |
1605 | 1603 | rt = atrtr_find(&at_hint); |
1606 | - if (!rt) | |
1607 | - return -ENETUNREACH; | |
1608 | - | |
1609 | 1604 | dev = rt->dev; |
1610 | 1605 | } |
1606 | + if (!rt) | |
1607 | + return -ENETUNREACH; | |
1611 | 1608 | |
1609 | + dev = rt->dev; | |
1610 | + | |
1612 | 1611 | SOCK_DEBUG(sk, "SK %p: Size needed %d, device %s\n", |
1613 | 1612 | sk, size, dev->name); |
1614 | 1613 | |
... | ... | @@ -1677,6 +1676,20 @@ |
1677 | 1676 | SOCK_DEBUG(sk, "SK %p: Loop back.\n", sk); |
1678 | 1677 | /* loop back */ |
1679 | 1678 | skb_orphan(skb); |
1679 | + if (ddp->deh_dnode == ATADDR_BCAST) { | |
1680 | + struct atalk_addr at_lo; | |
1681 | + | |
1682 | + at_lo.s_node = 0; | |
1683 | + at_lo.s_net = 0; | |
1684 | + | |
1685 | + rt = atrtr_find(&at_lo); | |
1686 | + if (!rt) { | |
1687 | + kfree_skb(skb); | |
1688 | + return -ENETUNREACH; | |
1689 | + } | |
1690 | + dev = rt->dev; | |
1691 | + skb->dev = dev; | |
1692 | + } | |
1680 | 1693 | ddp_dl->request(ddp_dl, skb, dev->dev_addr); |
1681 | 1694 | } else { |
1682 | 1695 | SOCK_DEBUG(sk, "SK %p: send out.\n", sk); |