1
0
This repository has been archived on 2024-07-22. You can view files and clone it, but cannot push or open issues or pull requests.
TP-Link_Archer-XR500v/EN7526G_3.18Kernel_SDK/bootrom/bootram/net/arp.c
2024-07-22 01:58:46 -03:00

138 lines
2.9 KiB
C
Executable File

#include "skbuff.h"
#include "eth.h"
#include "arp.h"
#include "osdep.h"
#define ARP_CACHE_SIZE 16
typedef struct arp_entry {
unsigned char ar_ha[ETH_ALEN];
unsigned long ar_ip;
} arp_entry;
static arp_entry arp_entrys;
static arp_entry arp_cache[ARP_CACHE_SIZE];
static int arp_chche_cur = 0;
int arp_init(void)
{
memset(&arp_entrys, 0, sizeof(arp_entry));
memset(arp_cache, 0, sizeof(arp_entry) * ARP_CACHE_SIZE);
return 0;
}
int arp_add_entry(unsigned char *ha, unsigned long ip)
{
memcpy(arp_entrys.ar_ha, ha, ETH_ALEN);
arp_entrys.ar_ip = htonl(ip);
return 0;
}
int arp_add_cache(unsigned char *ha, unsigned long ip)
{
int i;
for (i = 0; i < ARP_CACHE_SIZE; i++) {
if (ip == arp_cache[i].ar_ip)
break;
}
if (i == ARP_CACHE_SIZE) {
i = arp_chche_cur;
arp_chche_cur = (arp_chche_cur + 1) % ARP_CACHE_SIZE;
}
memcpy(arp_cache[i].ar_ha, ha, ETH_ALEN);
arp_cache[i].ar_ip = ip;
return 0;
}
int arp_send_req(unsigned long ip)
{
struct sk_buff *skb;
struct arphdr *arp_req;
unsigned char broadcast[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
skb = alloc_skb(ETH_HLEN + sizeof(struct arphdr));
eth_skb_reserve(skb);
arp_req = (struct arphdr *)skb_put(skb, sizeof(struct arphdr));
arp_req->ar_hrd = htons(ARPHRD_ETHER);
arp_req->ar_pro = htons(ETH_P_IP);
arp_req->ar_hln = 0x06;
arp_req->ar_pln = 0x04;
arp_req->ar_op = htons(ARPOP_REQUEST);
memcpy(arp_req->ar_sha, arp_entrys.ar_ha, ETH_ALEN);
arp_req->ar_sip = arp_entrys.ar_ip;
memset(arp_req->ar_tha, 0x00, ETH_ALEN);
arp_req->ar_tip = htonl(ip);
eth_send(skb, broadcast, ETH_P_ARP);
return 0;
}
int arp_send_rsp(struct arphdr *arp_hdr)
{
struct sk_buff *skb;
struct arphdr *arp_rsp;
skb = alloc_skb(ETH_HLEN + sizeof(struct arphdr));
eth_skb_reserve(skb);
arp_rsp = (struct arphdr *)skb_put(skb, sizeof(struct arphdr));
arp_rsp->ar_hrd = htons(ARPHRD_ETHER);
arp_rsp->ar_pro = htons(ETH_P_IP);
arp_rsp->ar_hln = 0x06;
arp_rsp->ar_pln = 0x04;
arp_rsp->ar_op = htons(ARPOP_REPLY);
memcpy(arp_rsp->ar_sha, arp_entrys.ar_ha, ETH_ALEN);
arp_rsp->ar_sip = arp_hdr->ar_tip;
memcpy(arp_rsp->ar_tha, arp_hdr->ar_sha, ETH_ALEN);
arp_rsp->ar_tip = arp_hdr->ar_sip;
eth_send(skb, arp_hdr->ar_sha, ETH_P_ARP);
return 0;
}
int arp_get_eth_addr(unsigned long ip, unsigned char *ha)
{
int i;
for (i = 0; i < ARP_CACHE_SIZE; i++) {
if (htonl(ip) == arp_cache[i].ar_ip) {
memcpy(ha, arp_cache[i].ar_ha, ETH_ALEN);
break;
}
}
if (i == ARP_CACHE_SIZE) {
arp_send_req(ip);
return -1;
}
return 0;
}
int arp_rcv_packet(sk_buff *skb)
{
struct arphdr *arp_hdr = (struct arphdr *)(skb->data);
if (arp_hdr->ar_tip != arp_entrys.ar_ip)
return 0;
//prom_printf("ar_tip=%x\n", arp_hdr->ar_tip);
//prom_printf("arp_entrys.ar_ip=%x\n", arp_entrys.ar_ip);
if (arp_hdr->ar_op == htons(ARPOP_REQUEST))
arp_send_rsp(arp_hdr);
arp_add_cache(arp_hdr->ar_sha, arp_hdr->ar_sip);
return 0;
}