[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>

authored by Oliver Dawid and committed by David S. Miller 64233bff ba645c16

+22 -9
+22 -9
net/appletalk/ddp.c
··· 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 && ··· 1442 1443 else 1443 1444 atif = atalk_find_interface(ddp->deh_dnet, ddp->deh_dnode); 1444 1445 1445 - /* Not ours, so we route the packet via the correct AppleTalk iface */ 1446 1446 if (!atif) { 1447 + /* Not ours, so we route the packet via the correct 1448 + * AppleTalk iface 1449 + */ 1447 1450 atalk_route_packet(skb, dev, ddp, &ddphv, origlen); 1448 1451 goto out; 1449 1452 } ··· 1593 1592 1594 1593 if (usat->sat_addr.s_net || usat->sat_addr.s_node == ATADDR_ANYNODE) { 1595 1594 rt = atrtr_find(&usat->sat_addr); 1596 - if (!rt) 1597 - return -ENETUNREACH; 1598 - 1599 1595 dev = rt->dev; 1600 1596 } else { 1601 1597 struct atalk_addr at_hint; ··· 1601 1603 at_hint.s_net = at->src_net; 1602 1604 1603 1605 rt = atrtr_find(&at_hint); 1604 - if (!rt) 1605 - return -ENETUNREACH; 1606 - 1607 1606 dev = rt->dev; 1608 1607 } 1608 + if (!rt) 1609 + return -ENETUNREACH; 1610 + 1611 + dev = rt->dev; 1609 1612 1610 1613 SOCK_DEBUG(sk, "SK %p: Size needed %d, device %s\n", 1611 1614 sk, size, dev->name); ··· 1676 1677 SOCK_DEBUG(sk, "SK %p: Loop back.\n", sk); 1677 1678 /* loop back */ 1678 1679 skb_orphan(skb); 1680 + if (ddp->deh_dnode == ATADDR_BCAST) { 1681 + struct atalk_addr at_lo; 1682 + 1683 + at_lo.s_node = 0; 1684 + at_lo.s_net = 0; 1685 + 1686 + rt = atrtr_find(&at_lo); 1687 + if (!rt) { 1688 + kfree_skb(skb); 1689 + return -ENETUNREACH; 1690 + } 1691 + dev = rt->dev; 1692 + skb->dev = dev; 1693 + } 1679 1694 ddp_dl->request(ddp_dl, skb, dev->dev_addr); 1680 1695 } else { 1681 1696 SOCK_DEBUG(sk, "SK %p: send out.\n", sk);