Commit 64233bffbb50f12e576c61d1698a573c8033004a

Authored by Oliver Dawid
Committed by David S. Miller
1 parent ba645c1602

[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

... ... @@ -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);