int arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir) { switch (dev->type) { case ARPHRD_ETHER: case ARPHRD_FDDI: case ARPHRD_IEEE802: ip_eth_mc_map(addr, haddr); return 0; case ARPHRD_IEEE802_TR: ip_tr_mc_map(addr, haddr); return 0; case ARPHRD_INFINIBAND: ip_ib_mc_map(addr, dev->broadcast, haddr); return 0; case ARPHRD_IPGRE: ip_ipgre_mc_map(addr, dev->broadcast, haddr); return 0; default: if (dir) { memcpy(haddr, dev->broadcast, dev->addr_len); return 0; } } return -EINVAL; }
HYFI_MC_STATIC unsigned int mc_pre_routing_hook(unsigned int hooknum, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int(*okfn)(struct sk_buff *)) { struct hyfi_net_bridge *hyfi_br = hyfi_bridge_get_by_dev(in); struct mc_struct *mc = MC_DEV(hyfi_br); struct ethhdr *eh = eth_hdr(skb); struct net_bridge_port *port; u8 dscp; if (!mc || skb->pkt_type != PACKET_HOST || (port = hyfi_br_port_get(in)) == NULL) goto out; dscp = MC_DSCP(mc->dscp) & (~INET_ECN_MASK); switch (ntohs(skb->protocol)) { case ETH_P_IP: { const struct iphdr *iph = ip_hdr(skb); if (ipv4_is_multicast(iph->daddr) && (!mc->enable_retag || (mc->enable_retag && (ipv4_get_dsfield(iph) == dscp)))) { ip_eth_mc_map(iph->daddr, eh->h_dest); if (mc->debug && printk_ratelimit()) { MC_PRINT("Decap the group "MC_IP4_STR" back to "MC_MAC_STR"\n", MC_IP4_FMT((u8 *)(&iph->daddr)) ,MC_MAC_FMT(eh->h_dest)); } skb->pkt_type = PACKET_MULTICAST; } } break; #ifdef HYBRID_MC_MLD case ETH_P_IPV6: { struct ipv6hdr *iph6 = ipv6_hdr(skb); if (ipv6_addr_is_multicast(&iph6->daddr) && (!mc->enable_retag || (mc->enable_retag && (ipv6_get_dsfield(iph6) == dscp)))) { ipv6_eth_mc_map(&iph6->daddr, eh->h_dest); if (mc->debug && printk_ratelimit()) { MC_PRINT("Decap the group "MC_IP6_STR" back to "MC_MAC_STR"\n", MC_IP6_FMT((__be16 *)(&iph6->daddr)) ,MC_MAC_FMT(eh->h_dest)); } skb->pkt_type = PACKET_MULTICAST; } } break; #endif } out: return NF_ACCEPT; }