/* * 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); }
/* * 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); }
/* * 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; }