1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
// https://github.com/saminiir/level-ip/blob/e9ceb08f01a5499b85f03e2d615309c655b97e8f/src/arp.c#L53
// https://github.com/chobits/tapip
// https://tools.ietf.org/html/rfc826
#include "arp.h"
#include "net_sys.h"
#include "inet.h"
#include "eth.h"
#include "netdev.h"
/*
*/
/*
static struct arp_cache_entry arp_cache[ARP_CACHE_LEN];
static int insert_arp_translation_table(struct arp_hdr *hdr, struct arp_ipv4 *data)
{
struct arp_cache_entry *entry;
for (int i = 0; i<ARP_CACHE_LEN; i++) {
entry = &arp_cache[i];
if (entry->state == ARP_FREE) {
entry->state = ARP_RESOLVED;
entry->hwtype = hdr->hwtype;
entry->sip = data->sip;
memcpy(entry->smac, data->smac, sizeof(entry->smac));
return 0;
}
}
return -1;
}
static int update_arp_translation_table(struct arp_hdr *hdr, struct arp_ipv4 *data)
{
struct arp_cache_entry *entry;
for (int i = 0; i<ARP_CACHE_LEN; i++) {
entry = &arp_cache[i];
if (entry->state == ARP_FREE) continue;
if (entry->hwtype == hdr->hwtype && entry->sip == data->sip) {
memcpy(entry->smac, data->smac, 6);
return 1;
}
}
return 0;
}
void arp_init()
{
memset(arp_cache, 0, ARP_CACHE_LEN * sizeof(struct arp_cache_entry));
}
*/
void arp_reply(struct netdev *netdev, struct eth_hdr *hdr, struct arp_hdr *arphdr)
{
struct arp_ipv4 *arpdata;
int len;
arpdata = (struct arp_ipv4 *) arphdr->data;
memcpy(arpdata->dmac, arpdata->smac, 6);
arpdata->dip = arpdata->sip;
memcpy(arpdata->smac, netdev->hwaddr, 6);
arpdata->sip = netdev->ip;
arphdr->opcode = ARP_REPLY;
arphdr->opcode = htons(arphdr->opcode);
arphdr->hwtype = htons(arphdr->hwtype);
arphdr->protype = htons(arphdr->protype);
len = sizeof(struct arp_hdr) + sizeof(struct arp_ipv4);
netdev_transmit(netdev, hdr, ETH_P_ARP, len, arpdata->dmac);
}
void arp_incoming(struct netdev *netdev, struct eth_hdr *hdr)
{
struct arp_hdr *arphdr;
struct arp_ipv4 *arpdata;
int merge = 0;
arphdr = (struct arp_hdr *) hdr->payload;
arphdr->hwtype = ntohs(arphdr->hwtype);
arphdr->protype = ntohs(arphdr->protype);
arphdr->opcode = ntohs(arphdr->opcode);
if (arphdr->hwtype != ARP_ETHERNET) {
klog("Unsupported HW type\n");
return;
}
if (arphdr->protype != ARP_IPV4) {
klog("Unsupported protocol\n");
return;
}
arpdata = (struct arp_ipv4 *) arphdr->data;
// merge = update_arp_translation_table(arphdr, arpdata);
klog("incoming arp\n");
if (netdev->ip != arpdata->dip) {
klog("ARP was not for us\n");
}
// if (!merge && insert_arp_translation_table(arphdr, arpdata) != 0) {
// klog("ERR: No free space in ARP translation table\n");
// }
switch (arphdr->opcode) {
case ARP_REQUEST:
// klog("Arp Reply");
arp_reply(netdev, hdr, arphdr);
break;
default:
klog("Opcode not supported\n");
break;
}
}
|