/* * Description: This function is called by Netfilter when packet hits * the bridge pre routing hook. All IP packets are given * to EMFL for its processing. * * Input: skb - Pointer to the packet buffer. Other parameters * are not used. * * Return: Returns the value indicating packet can be forwarded * or packet is stolen. */ static uint32 emf_br_pre_hook(uint32 hook, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int32 (*okfn)(struct sk_buff *)) { emf_info_t *emfi; EMF_INFO("Frame at BR_PRE_HOOK received from if %p %s\n", skb->dev, skb->dev->name); /* Find the bridge that the receive interface corresponds to */ emfi = emf_instance_find_by_ifptr(emf, skb->dev); if (emfi == NULL) { EMF_INFO("No EMF processing needed for unknown ports\n"); return (NF_ACCEPT); } /* Non IP packet received from LAN port is returned back to * bridge. */ if (skb->protocol != __constant_htons(ETH_P_IP)) { EMF_INFO("Ignoring non IP packets from LAN ports\n"); return (NF_ACCEPT); } EMF_DUMP_PKT(skb->data); return (emfc_input(emfi->emfci, skb, skb->dev, PKTDATA(NULL, skb), FALSE)); }
/* * Description: This function is called by EMFL common code when it wants * to forward the packet on to a specific port. It adds the * MAC header and queues the frame to the interface. * * Input: emfi - EMF instance information * skb - Pointer to the packet buffer. * mgrp_ip - Multicast destination address. * txif - Interface to send the frame on. * * Return: SUCCESS or FAILURE. */ int32 emf_forward(emf_info_t *emfi, struct sk_buff *skb, uint32 mgrp_ip, struct net_device *txif, bool rt_port) { struct ether_header *eh; EMF_DEBUG("Forwarding the frame %p on to %s\n", skb, txif->name); #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) ASSERT(txif->br_port); /* Send only when the port is in forwarding state */ if (EMF_BRPORT_STATE(txif) != BR_STATE_FORWARDING) { EMF_INFO("Dropping the frame as the port %s is not in" " FORWARDING state\n", txif->name); kfree_skb(skb); return (FAILURE); } /* there is no access to the "bridge" struct from netif in 2.6.36 */ #endif eh = (struct ether_header *)skb_push(skb, ETH_HLEN); /* No need to fill the ether header fields for packets received * from LAN ports. */ if (rt_port) { eh->ether_type = __constant_htons(ETH_P_IP); ETHER_FILL_MCAST_ADDR_FROM_IP(eh->ether_dhost, mgrp_ip); memcpy(eh->ether_shost, skb->dev->dev_addr, skb->dev->addr_len); } EMF_INFO("Group Addr: %02x:%02x:%02x:%02x:%02x:%02x\n", eh->ether_dhost[0], eh->ether_dhost[1], eh->ether_dhost[2], eh->ether_dhost[3], eh->ether_dhost[4], eh->ether_dhost[5]); /* Send buffer as if it is delivered by bridge */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) skb_reset_mac_header(skb); #else skb->mac.raw = skb->data; #endif skb->dev = txif; dev_queue_xmit(skb); return (SUCCESS); }
/* * Description: This function is called by Netfilter when packet hits * the ip post routing hook. The packet is sent to EMFL * only when it is going on to bridge port. * * Input: skb - Pointer to the packet buffer. Other parameters * are not used. * * Return: Returns the value indicating packet can be forwarded * or packet is stolen. */ static uint32 emf_ip_post_hook(uint32 hook, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int32 (*okfn)(struct sk_buff *)) { emf_info_t *emfi; ASSERT(skb->protocol == __constant_htons(ETH_P_IP)); EMF_DEBUG("Frame at IP_POST_HOOK going to if %p %s\n", skb->dev, skb->dev->name); /* Find the LAN that the bridge interface corresponds to */ emfi = emf_instance_find_by_brptr(emf, skb->dev); if (emfi == NULL) { EMF_INFO("No EMF processing needed for unknown ports\n"); return (NF_ACCEPT); } EMF_DUMP_PKT(skb->data); return (emfc_input(emfi->emfci, skb, skb->dev, PKTDATA(NULL, skb), TRUE)); }
/* * Description: This function is called by Netfilter when packet hits * the ip post routing hook. The packet is sent to EMFL * only when it is going on to bridge port. * * Input: pskb - Pointer to the packet buffer. Other parameters * are not used. * * Return: Returns the value indicating packet can be forwarded * or packet is stolen. */ static uint32 emf_ip_post_hook( uint32 hook, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) struct sk_buff *skb, #else struct sk_buff **pskb, #endif const struct net_device *in, const struct net_device *out, int32 (*okfn)(struct sk_buff *)) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) struct sk_buff **pskb = &skb; #endif emf_info_t *emfi; ASSERT((*pskb)->protocol == __constant_htons(ETH_P_IP)); EMF_DEBUG("Frame at IP_POST_HOOK going to if %p %s\n", (*pskb)->dev, (*pskb)->dev->name); /* Find the LAN that the bridge interface corresponds to */ emfi = emf_instance_find_by_brptr(emf, (*pskb)->dev); if (emfi == NULL) { EMF_INFO("No EMF processing needed for unknown ports\n"); return (NF_ACCEPT); } EMF_DUMP_PKT((*pskb)->data); return (emfc_input(emfi->emfci, *pskb, (*pskb)->dev, PKTDATA(NULL, *pskb), TRUE)); }
/* * Description: This function is called when the user application enables * EMF on a bridge interface. It primarily allocates memory * for instance data and calls the common code init function. * * Input: emf - EMF module global data pointer * inst_id - EMF instance name * br_ptr - Bridge device pointer */ static emf_info_t * emf_instance_add(emf_struct_t *emf, int8 *inst_id, struct net_device *br_ptr) { emf_info_t *emfi; osl_t *osh; #ifdef CONFIG_PROC_FS uint8 proc_name[64]; #endif /* CONFIG_PROC_FS */ emfc_wrapper_t emfl; if (emf->inst_count > EMF_MAX_INST) { EMF_ERROR("Max instance limit %d exceeded\n", EMF_MAX_INST); return (NULL); } emf->inst_count++; EMF_INFO("Creating EMF instance for %s\n", inst_id); osh = osl_attach(NULL, PCI_BUS, FALSE); ASSERT(osh); /* Allocate os specfic EMF info object */ emfi = MALLOC(osh, sizeof(emf_info_t)); if (emfi == NULL) { EMF_ERROR("Out of memory allocating emf_info\n"); osl_detach(osh); return (NULL); } emfi->osh = osh; /* Save the EMF instance identifier */ strncpy(emfi->inst_id, inst_id, IFNAMSIZ); emfi->inst_id[IFNAMSIZ - 1] = 0; /* Save the device pointer */ emfi->br_dev = br_ptr; /* Fill the linux wrapper specific functions */ emfl.forward_fn = (forward_fn_ptr)emf_forward; emfl.sendup_fn = (sendup_fn_ptr)emf_sendup; emfl.hooks_register_fn = (hooks_register_fn_ptr)emf_hooks_register; emfl.hooks_unregister_fn = (hooks_unregister_fn_ptr)emf_hooks_unregister; /* Initialize EMFC instance */ if ((emfi->emfci = emfc_init(inst_id, (void *)emfi, osh, &emfl)) == NULL) { EMF_ERROR("EMFC init failed\n"); MFREE(osh, emfi, sizeof(emf_info_t)); osl_detach(osh); return (NULL); } EMF_INFO("Created EMFC instance for %s\n", inst_id); /* Initialize the iflist head */ emfi->iflist_head = NULL; #ifdef CONFIG_PROC_FS sprintf(proc_name, "net/emf_stats_%s", inst_id); create_proc_read_entry(proc_name, 0, 0, emf_stats_get, emfi); sprintf(proc_name, "net/emfdb_%s", inst_id); create_proc_read_entry(proc_name, 0, 0, emf_mfdb_list, emfi); #endif /* CONFIG_PROC_FS */ /* Add to the global EMF instance list */ emfi->next = emf->list_head; emf->list_head = emfi; return (emfi); }