diff options
Diffstat (limited to 'drivers/staging/bcm/Arp.c')
-rw-r--r-- | drivers/staging/bcm/Arp.c | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/drivers/staging/bcm/Arp.c b/drivers/staging/bcm/Arp.c new file mode 100644 index 000000000000..d60d8593d2ef --- /dev/null +++ b/drivers/staging/bcm/Arp.c @@ -0,0 +1,94 @@ + +/* + * File Name: Arp.c + * Abstract: This file contains the routines for handling ARP PACKETS + */ +#include "headers.h" +#define ARP_PKT_SIZE 60 + +/* ========================================================================= + * Function - reply_to_arp_request() + * + * Description - When this host tries to broadcast ARP request packet through + * the virtual interface (veth0), reply directly to upper layer. + * This function allocates a new skb for ARP reply packet, + * fills in the fields of the packet and then sends it to + * upper layer. + * + * Parameters - skb: Pointer to sk_buff structure of the ARP request pkt. + * + * Returns - None + * =========================================================================*/ + +VOID +reply_to_arp_request(struct sk_buff *skb) +{ + PMINI_ADAPTER Adapter; + struct ArpHeader *pArpHdr = NULL; + struct ethhdr *pethhdr = NULL; + UCHAR uiIPHdr[4]; + /* Check for valid skb */ + if(skb == NULL) + { + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "Invalid skb: Cannot reply to ARP request\n"); + return; + } + + + Adapter = GET_BCM_ADAPTER(skb->dev); + /* Print the ARP Request Packet */ + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, ARP_RESP, DBG_LVL_ALL, "ARP Packet Dump :"); + BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_TX, ARP_RESP, DBG_LVL_ALL, (PUCHAR)(skb->data), skb->len); + + /* + * Extract the Ethernet Header and Arp Payload including Header + */ + pethhdr = (struct ethhdr *)skb->data; + pArpHdr = (struct ArpHeader *)(skb->data+ETH_HLEN); + + if(Adapter->bETHCSEnabled) + { + if(memcmp(pethhdr->h_source, Adapter->dev->dev_addr, ETH_ALEN)) + { + bcm_kfree_skb(skb); + return; + } + } + + // Set the Ethernet Header First. + memcpy(pethhdr->h_dest, pethhdr->h_source, ETH_ALEN); + if(!memcmp(pethhdr->h_source, Adapter->dev->dev_addr, ETH_ALEN)) + { + pethhdr->h_source[5]++; + } + + /* Set the reply to ARP Reply */ + pArpHdr->arp.ar_op = ntohs(ARPOP_REPLY); + + /* Set the HW Address properly */ + memcpy(pArpHdr->ar_sha, pethhdr->h_source, ETH_ALEN); + memcpy(pArpHdr->ar_tha, pethhdr->h_dest, ETH_ALEN); + + // Swapping the IP Adddress + memcpy(uiIPHdr,pArpHdr->ar_sip,4); + memcpy(pArpHdr->ar_sip,pArpHdr->ar_tip,4); + memcpy(pArpHdr->ar_tip,uiIPHdr,4); + + /* Print the ARP Reply Packet */ + + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, ARP_RESP, DBG_LVL_ALL, "ARP REPLY PACKET: "); + + /* Send the Packet to upper layer */ + BCM_DEBUG_PRINT_BUFFER(Adapter,DBG_TYPE_TX, ARP_RESP, DBG_LVL_ALL, (PUCHAR)(skb->data), skb->len); + + skb->protocol = eth_type_trans(skb,skb->dev); + skb->pkt_type = PACKET_HOST; + +// skb->mac.raw=skb->data+LEADER_SIZE; + skb_set_mac_header (skb, LEADER_SIZE); + netif_rx(skb); + BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, ARP_RESP, DBG_LVL_ALL, "<=============\n"); + return; +} + + |