[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 continue; 101 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) 105 goto found; 106 107 if (to->sat_addr.s_net == at->src_net && ··· 1442 else 1443 atif = atalk_find_interface(ddp->deh_dnet, ddp->deh_dnode); 1444 1445 - /* Not ours, so we route the packet via the correct AppleTalk iface */ 1446 if (!atif) { 1447 atalk_route_packet(skb, dev, ddp, &ddphv, origlen); 1448 goto out; 1449 } ··· 1593 1594 if (usat->sat_addr.s_net || usat->sat_addr.s_node == ATADDR_ANYNODE) { 1595 rt = atrtr_find(&usat->sat_addr); 1596 - if (!rt) 1597 - return -ENETUNREACH; 1598 - 1599 dev = rt->dev; 1600 } else { 1601 struct atalk_addr at_hint; ··· 1601 at_hint.s_net = at->src_net; 1602 1603 rt = atrtr_find(&at_hint); 1604 - if (!rt) 1605 - return -ENETUNREACH; 1606 - 1607 dev = rt->dev; 1608 } 1609 1610 SOCK_DEBUG(sk, "SK %p: Size needed %d, device %s\n", 1611 sk, size, dev->name); ··· 1676 SOCK_DEBUG(sk, "SK %p: Loop back.\n", sk); 1677 /* loop back */ 1678 skb_orphan(skb); 1679 ddp_dl->request(ddp_dl, skb, dev->dev_addr); 1680 } else { 1681 SOCK_DEBUG(sk, "SK %p: send out.\n", sk);
··· 100 continue; 101 102 if (to->sat_addr.s_net == ATADDR_ANYNET && 103 + to->sat_addr.s_node == ATADDR_BCAST) 104 goto found; 105 106 if (to->sat_addr.s_net == at->src_net && ··· 1443 else 1444 atif = atalk_find_interface(ddp->deh_dnet, ddp->deh_dnode); 1445 1446 if (!atif) { 1447 + /* Not ours, so we route the packet via the correct 1448 + * AppleTalk iface 1449 + */ 1450 atalk_route_packet(skb, dev, ddp, &ddphv, origlen); 1451 goto out; 1452 } ··· 1592 1593 if (usat->sat_addr.s_net || usat->sat_addr.s_node == ATADDR_ANYNODE) { 1594 rt = atrtr_find(&usat->sat_addr); 1595 dev = rt->dev; 1596 } else { 1597 struct atalk_addr at_hint; ··· 1603 at_hint.s_net = at->src_net; 1604 1605 rt = atrtr_find(&at_hint); 1606 dev = rt->dev; 1607 } 1608 + if (!rt) 1609 + return -ENETUNREACH; 1610 + 1611 + dev = rt->dev; 1612 1613 SOCK_DEBUG(sk, "SK %p: Size needed %d, device %s\n", 1614 sk, size, dev->name); ··· 1677 SOCK_DEBUG(sk, "SK %p: Loop back.\n", sk); 1678 /* loop back */ 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 + } 1694 ddp_dl->request(ddp_dl, skb, dev->dev_addr); 1695 } else { 1696 SOCK_DEBUG(sk, "SK %p: send out.\n", sk);