/* * 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 handles the OS specific processing * required for configuration commands. * * Input: data - Configuration command parameters */ void emf_cfg_request_process(emf_cfg_request_t *cfg) { emf_info_t *emfi; emf_cfg_mfdb_t *mfdb; emf_cfg_uffp_t *uffp; emf_cfg_rtport_t *rtport; emf_cfg_if_t *if_cfg; emf_iflist_t *iflist_prev; struct net_device *if_ptr, *br_ptr; if (cfg == NULL) { cfg->status = EMFCFG_STATUS_FAILURE; cfg->size = sprintf(cfg->arg, "Invalid input buffer passed\n"); return; } /* Validate the instance identifier */ br_ptr = emf_if_name_validate(cfg->inst_id); if (br_ptr == NULL) { cfg->status = EMFCFG_STATUS_FAILURE; cfg->size = sprintf(cfg->arg, "Unknown instance identifier %s\n", cfg->inst_id); return; } /* Locate the EMF instance */ emfi = emf_instance_find_by_brptr(emf, br_ptr); if ((emfi == NULL) && (cfg->command_id != EMFCFG_CMD_BR_ADD)) { cfg->status = EMFCFG_STATUS_FAILURE; cfg->size = sprintf(cfg->arg, "Invalid instance identifier %s\n", cfg->inst_id); return; } /* Convert the interface name in arguments to interface pointer */ switch (cfg->command_id) { case EMFCFG_CMD_MFDB_ADD: case EMFCFG_CMD_MFDB_DEL: mfdb = (emf_cfg_mfdb_t *)cfg->arg; mfdb->if_ptr = emf_if_name_validate(mfdb->if_name); if (mfdb->if_ptr == NULL) { cfg->status = EMFCFG_STATUS_FAILURE; cfg->size = sprintf(cfg->arg, "Invalid interface specified " "during MFDB entry add/delete\n"); return; } /* The interfaces specified should be in the iflist */ if ((strncmp(mfdb->if_name, "wds", 3) != 0) && (emf_iflist_find(emf, emfi, mfdb->if_ptr, &iflist_prev) == NULL)) { cfg->status = EMFCFG_STATUS_FAILURE; cfg->size = sprintf(cfg->arg, "Interface not part of bridge %s\n", br_ptr->name); return; } emfc_cfg_request_process(emfi->emfci, cfg); break; case EMFCFG_CMD_IF_ADD: case EMFCFG_CMD_IF_DEL: /* Add/Del the interface to/from the global list */ if_cfg = (emf_cfg_if_t *)cfg->arg; if_ptr = emf_if_name_validate(if_cfg->if_name); if (if_ptr == NULL) { cfg->status = EMFCFG_STATUS_FAILURE; cfg->size = sprintf(cfg->arg, "Invalid interface specified\n"); return; } if (cfg->command_id == EMFCFG_CMD_IF_ADD) { if (emf_iflist_add(emf, emfi, if_ptr) != SUCCESS) { cfg->status = EMFCFG_STATUS_FAILURE; cfg->size = sprintf(cfg->arg, "Interface add failed\n"); return; } if (emfc_iflist_add(emfi->emfci, if_ptr) != SUCCESS) { emf_iflist_del(emf, emfi, if_ptr); cfg->status = EMFCFG_STATUS_FAILURE; cfg->size = sprintf(cfg->arg, "Interface add failed\n"); return; } } if (cfg->command_id == EMFCFG_CMD_IF_DEL) { if ((emf_iflist_del(emf, emfi, if_ptr) != SUCCESS) || (emfc_iflist_del(emfi->emfci, if_ptr) != SUCCESS)) { cfg->status = EMFCFG_STATUS_FAILURE; cfg->size = sprintf(cfg->arg, "Interface delete failed\n"); return; } } cfg->status = EMFCFG_STATUS_SUCCESS; break; case EMFCFG_CMD_IF_LIST: if (emf_iflist_list(emfi, (emf_cfg_if_list_t *)cfg->arg, cfg->size) != SUCCESS) { cfg->status = EMFCFG_STATUS_FAILURE; cfg->size += sprintf(cfg->arg, "EMF if list get failed\n"); break; } cfg->status = EMFCFG_STATUS_SUCCESS; break; case EMFCFG_CMD_BR_ADD: if (emfi != NULL) { cfg->status = EMFCFG_STATUS_FAILURE; cfg->size = sprintf(cfg->arg, "EMF already configured for %s\n", cfg->inst_id); return; } /* Create a new EMF instance corresponding to the bridge * interface. */ emfi = emf_instance_add(emf, cfg->inst_id, br_ptr); if (emfi == NULL) { cfg->status = EMFCFG_STATUS_FAILURE; cfg->size = sprintf(cfg->arg, "EMF add on %s failed\n", cfg->inst_id); return; } cfg->status = EMFCFG_STATUS_SUCCESS; break; case EMFCFG_CMD_BR_DEL: /* Delete and free the EMF instance */ if (emf_instance_del(emf, emfi) != SUCCESS) { cfg->status = EMFCFG_STATUS_FAILURE; cfg->size = sprintf(cfg->arg, "EMF delete on %s failed\n", cfg->inst_id); return; } cfg->status = EMFCFG_STATUS_SUCCESS; break; case EMFCFG_CMD_UFFP_ADD: case EMFCFG_CMD_UFFP_DEL: uffp = (emf_cfg_uffp_t *)cfg->arg; if_ptr = uffp->if_ptr = emf_if_name_validate(uffp->if_name); /* FALLTHRU */ case EMFCFG_CMD_RTPORT_ADD: case EMFCFG_CMD_RTPORT_DEL: rtport = (emf_cfg_rtport_t *)cfg->arg; if_ptr = rtport->if_ptr = emf_if_name_validate(rtport->if_name); if (if_ptr == NULL) { cfg->status = EMFCFG_STATUS_FAILURE; cfg->size = sprintf(cfg->arg, "Invalid iface specified for deletion\n"); return; } if (emf_iflist_find(emf, emfi, if_ptr, &iflist_prev) == NULL) { cfg->status = EMFCFG_STATUS_FAILURE; cfg->size = sprintf(cfg->arg, "Interface not part of bridge %s\n", br_ptr->name); return; } emfc_cfg_request_process(emfi->emfci, cfg); break; default: emfc_cfg_request_process(emfi->emfci, cfg); break; } return; }