示例#1
0
/*
 * 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));
}
示例#2
0
文件: emf_linux.c 项目: gygy/asuswrt
/*
 * 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));
}
示例#3
0
/*
 * 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;
}