/* ======================================================================== Routine Description: Forward the received packet. Arguments: pPacket - the received packet Return Value: None Note: ======================================================================== */ UINT32 BG_FTPH_PacketFromApHandle( IN PNDIS_PACKET pPacket) { struct net_device *pNetDev; struct sk_buff *pRxPkt; struct net_bridge_fdb_entry *pSrcFdbEntry, *pDstFdbEntry; /* init */ pRxPkt = RTPKT_TO_OSPKT(pPacket); pNetDev = pRxPkt->dev; /* if pNetDev is promisc mode ??? */ DBGPRINT(RT_DEBUG_INFO, ("ft bg> BG_FTPH_PacketFromApHandle\n")); if (pNetDev != NULL) { if (pNetDev->br_port != NULL) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,12) pDstFdbEntry = br_fdb_get_hook(pNetDev->br_port->br, pRxPkt->data); pSrcFdbEntry = br_fdb_get_hook(pNetDev->br_port->br, pRxPkt->data + 6); #else /* br_fdb_get is not exported symbol, need exported in net/bridge/br.c */ pDstFdbEntry = br_fdb_get(pNetDev->br_port->br, pRxPkt->data); pSrcFdbEntry = br_fdb_get(pNetDev->br_port->br, pRxPkt->data + 6); #endif /* check destination address in bridge forwarding table */ if ((pSrcFdbEntry == NULL) || (pDstFdbEntry == NULL) || (pDstFdbEntry->is_local) || (pDstFdbEntry->dst == NULL) || (pDstFdbEntry->dst->dev == NULL) || (pDstFdbEntry->dst->dev == pNetDev) || (pNetDev->br_port->state != BR_STATE_FORWARDING) || ((pSrcFdbEntry->dst != NULL) && (pSrcFdbEntry->dst->dev != NULL) && (pSrcFdbEntry->dst->dev != pNetDev))) { goto LabelPassToUpperLayer; } /* End of if */ if ((!pDstFdbEntry->is_local) && (pDstFdbEntry->dst != NULL) && (pDstFdbEntry->dst->dev != NULL)) { pRxPkt->dev = pDstFdbEntry->dst->dev; pDstFdbEntry->dst->dev->hard_start_xmit(pRxPkt, pDstFdbEntry->dst->dev); return 0; } /* End of if */ } /* End of if */ } /* End of if */ LabelPassToUpperLayer: DBGPRINT(RT_DEBUG_TRACE, ("ft bg> Pass packet to bridge module.\n")); return 1; } /* End of BG_FTPH_PacketFromApHandle */
static int __br_dev_xmit(struct sk_buff *skb, struct net_device *dev) { struct net_bridge *br; unsigned char *dest; struct net_bridge_fdb_entry *dst; br = dev->priv; br->statistics.tx_packets++; br->statistics.tx_bytes += skb->len; dest = skb->mac.raw = skb->data; skb_pull(skb, ETH_HLEN); if (dest[0] & 1) { br_flood_deliver(br, skb, 0); return 0; } if ((dst = br_fdb_get(br, dest)) != NULL) { br_deliver(dst->dst, skb); br_fdb_put(dst); return 0; } br_flood_deliver(br, skb, 0); return 0; }
static int br_handle_frame_finish(struct sk_buff *skb) { struct net_bridge *br; unsigned char *dest; struct net_bridge_fdb_entry *dst; struct net_bridge_port *p; int passedup; dest = skb->mac.ethernet->h_dest; p = skb->dev->br_port; if (p == NULL) goto err_nolock; br = p->br; read_lock(&br->lock); if (skb->dev->br_port == NULL) goto err; passedup = 0; if (br->dev.flags & IFF_PROMISC) { struct sk_buff *skb2; skb2 = skb_clone(skb, GFP_ATOMIC); if (skb2 != NULL) { passedup = 1; br_pass_frame_up(br, skb2); } } if (dest[0] & 1) { br_flood_forward(br, skb, !passedup); if (!passedup) br_pass_frame_up(br, skb); goto out; } dst = br_fdb_get(br, dest); if (dst != NULL && dst->is_local) { if (!passedup) br_pass_frame_up(br, skb); else kfree_skb(skb); br_fdb_put(dst); goto out; } if (dst != NULL) { br_forward(dst->dst, skb); br_fdb_put(dst); goto out; } br_flood_forward(br, skb, 0); out: read_unlock(&br->lock); return 0; err: read_unlock(&br->lock); err_nolock: kfree_skb(skb); return 0; }
static int __br_dev_xmit(struct sk_buff *skb, struct net_device *dev) { struct net_bridge *br; unsigned char *dest; struct net_bridge_fdb_entry *dst; #ifdef IGMP_SNOOPING struct iphdr *iph; unsigned int ipaddr=0; unsigned char proto=0; //unsigned char reserved=0; extern int igmpsnoopenabled; iph = skb->nh.iph; ipaddr = iph->daddr; proto = iph->protocol; //Brad disable 20080619 // if ((ipaddr&0xF0FFFF00) == 0xE0000000) // reserved=1; #endif br = dev->priv; br->statistics.tx_packets++; br->statistics.tx_bytes += skb->len; dest = skb->mac.raw = skb->data; skb_pull(skb, ETH_HLEN); if (dest[0] & 1) { #ifdef IGMP_SNOOPING if(igmpsnoopenabled && (MULTICAST_MAC(dest) || IPV6_MULTICAST_MAC(dest))&& (proto != IPPROTO_IGMP) && (ipaddr != 0xEFFFFFFA) //&& (reserved == 0) ) { if ((dst = br_fdb_get(br, dest)) != NULL) { br_multicast_deliver(br, dst, skb, 0); br_fdb_put(dst); } else { br_flood_deliver(br, skb, 0); } } else { // broadcast br_flood_deliver(br, skb, 0); } return 0; #else br_flood_deliver(br, skb, 0); return 0; #endif } if ((dst = br_fdb_get(br, dest)) != NULL) { #ifdef NAT_SPEEDUP if (skb->dst && skb->dst->hh && skb->dst->hh->fdb_cache==NULL) { skb->dst->hh->fdb_cache = (void*)dst; dst->hh_ptr = skb->dst->hh; } #endif br_deliver(dst->dst, skb); br_fdb_put(dst); return 0; } br_flood_deliver(br, skb, 0); return 0; }