Beispiel #1
0
/*
 * Description: This function is called by IGS Common code when it wants
 *              to send a packet on to all the LAN ports. It allocates
 *              the native OS packet buffer, adds mac header and forwards
 *              a copy of frame on to LAN ports.
 *
 * Input:       igs_info - IGS instance information.
 *              ip       - Pointer to the buffer containing the frame to
 *                         send.
 *              length   - Length of the buffer.
 *              mgrp_ip  - Multicast destination address.
 *
 * Return:      SUCCESS or FAILURE
 */
int32
igs_broadcast(igs_info_t *igs_info, uint8 *ip, uint32 length, uint32 mgrp_ip)
{
	struct sk_buff *skb;
	struct net_device *br_dev;
	struct ether_header *eh;

	br_dev = igs_info->br_dev;

	ASSERT(br_dev);

	if ((br_dev->flags & IFF_UP) == 0)
	{
		IGS_ERROR("Bridge interface %s is down\n", br_dev->name);
		return (FAILURE);
	}

	skb = dev_alloc_skb(length + ETHER_HDR_LEN);

	if (skb == NULL)
	{
		IGS_ERROR("Out of memory allocating IGMP Query packet\n");
		return (FAILURE);
	}

	IGS_DEBUG("Allocated pkt buffer for IGMP Query\n");

	skb_pull(skb, ETHER_HDR_LEN);
	memcpy(skb->data, ip, length);
	skb_put(skb, length);

	/* Add the ethernet header */
	eh = (struct ether_header *)skb_push(skb, ETH_HLEN);
	eh->ether_type = __constant_htons(ETH_P_IP);
	eh->ether_dhost[0] = 0x01;
	eh->ether_dhost[1] = 0x00;
	eh->ether_dhost[2] = 0x5e;
	eh->ether_dhost[5] = mgrp_ip & 0xff; mgrp_ip >>= 8;
	eh->ether_dhost[4] = mgrp_ip & 0xff; mgrp_ip >>= 8;
	eh->ether_dhost[3] = mgrp_ip & 0x7f;

	/* Send the frame on to the bridge device */
	memcpy(eh->ether_shost, br_dev->dev_addr, br_dev->addr_len);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22)
	skb_reset_mac_header(skb);
#else
	skb->mac.raw = skb->data;
#endif
	skb->dev = br_dev;
	dev_queue_xmit(skb);

	IGS_DEBUG("IGMP Query sent on %s\n", br_dev->name);

	return (SUCCESS);
}
Beispiel #2
0
/*
 * Description: This function is called by Linux kernel when user
 *              applications sends a message on netlink socket. It
 *              dequeues the message, calls the functions to process
 *              the commands and sends the result back to user.
 *
 * Input:       skb  - Kernel socket structure
 */
static void
igs_netlink_sock_cb(struct sk_buff *skb)
{
	struct nlmsghdr	*nlh;

	nlh = nlmsg_hdr(skb);
	IGS_DEBUG("Length of the command buffer %d\n", nlh->nlmsg_len);

	/* Check the buffer for min size */
	if (skb->len < NLMSG_SPACE(0) || skb->len < nlh->nlmsg_len ||
		nlh->nlmsg_len < NLMSG_LENGTH(sizeof(igs_cfg_request_t)))
	{
		IGS_ERROR("Configuration request size not > %d\n",
		          sizeof(igs_cfg_request_t));
		return;
	}

	skb = skb_clone(skb, GFP_KERNEL);
	if (skb == NULL)
		return;
	nlh = nlmsg_hdr(skb);

	/* Process the message */
	igs_cfg_request_process((igs_cfg_request_t *)NLMSG_DATA(nlh));

	/* Send the result to user process */
	NETLINK_CB(skb).pid = nlh->nlmsg_pid;
	NETLINK_CB(skb).dst_group = 0;

	netlink_unicast(igs.nl_sk, skb, nlh->nlmsg_pid, MSG_DONTWAIT);
}
Beispiel #3
0
/*
 * Description: This function is called by Linux kernel when user
 *              applications sends a message on netlink socket. It
 *              dequeues the message, calls the functions to process
 *              the commands and sends the result back to user.
 *
 * Input:       sk  - Kernel socket structure
 *              len - Length of the message received from user app.
 */
static void
igs_netlink_sock_cb(struct sock *sk, int32 len)
{
	struct sk_buff	*skb;
	struct nlmsghdr	*nlh = NULL;
	uint8 *data = NULL;

	IGS_DEBUG("Length of the command buffer %d\n", len);

	/* Dequeue the message from netlink socket */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
	while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL)
#else
	while ((skb = skb_dequeue(&sk->receive_queue)) != NULL)
#endif
	{
		/* Check the buffer for min size */
		if (skb->len < sizeof(igs_cfg_request_t))
		{
			IGS_ERROR("Configuration request size not > %d\n",
			          sizeof(igs_cfg_request_t));
			return;
		}


		/* Buffer contains netlink header followed by data */
		nlh = (struct nlmsghdr *)skb->data;
		data = NLMSG_DATA(nlh);

		/* Process the message */
		igs_cfg_request_process((igs_cfg_request_t *)data);

		/* Send the result to user process */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
		NETLINK_CB(skb).pid = nlh->nlmsg_pid;
		NETLINK_CB(skb).dst_group = 0;
#else
		NETLINK_CB(skb).groups = 0;
		NETLINK_CB(skb).pid = 0;
		NETLINK_CB(skb).dst_groups = 0;
		NETLINK_CB(skb).dst_pid = nlh->nlmsg_pid;
#endif

		netlink_unicast(igs.nl_sk, skb, nlh->nlmsg_pid, MSG_DONTWAIT);
	}

	return;
}