summaryrefslogtreecommitdiff
path: root/network/arp.c
diff options
context:
space:
mode:
Diffstat (limited to 'network/arp.c')
-rw-r--r--network/arp.c123
1 files changed, 96 insertions, 27 deletions
diff --git a/network/arp.c b/network/arp.c
index f86c732..de6d898 100644
--- a/network/arp.c
+++ b/network/arp.c
@@ -20,9 +20,28 @@ struct ARP_DATA {
// above). If IPv4 can just be a "u32" type.
};
+struct ARP_TABLE_ENTRY {
+ uint8_t is_used;
+ uint8_t mac[6];
+ uint8_t ip[4];
+};
+
+struct ARP_TABLE_ENTRY arp_table[10] = {0};
+
// FIXME: This is hardcoded, don't do this.
uint8_t ip_address[4] = {10, 0, 2, 15};
+struct ARP_TABLE_ENTRY *find_arp_entry_to_use(void) {
+ // This does not need to find a "free" entry as a ARP table is
+ // just a cache, it just has to pick a entry efficently.
+ for (int i = 0; i < 10; i++) {
+ if (!arp_table[i].is_used) {
+ return &arp_table[i];
+ }
+ }
+ return &arp_table[0];
+}
+
void print_mac(const char *str, uint8_t *mac) {
kprintf("%s: ", str);
for (int i = 0; i < 6; i++) {
@@ -33,7 +52,7 @@ void print_mac(const char *str, uint8_t *mac) {
kprintf("\n");
}
-void print_ip(const char *str, uint8_t *ip) {
+void print_ip(const char *str, const uint8_t *ip) {
kprintf("%s: ", str);
for (int i = 0; i < 4; i++) {
kprintf("%d", ip[i]);
@@ -43,42 +62,92 @@ void print_ip(const char *str, uint8_t *ip) {
kprintf("\n");
}
+void send_arp_request(const uint8_t ip[4]) {
+ struct ARP_DATA data;
+ data.htype = htons(1);
+ data.ptype = htons(0x0800);
+
+ data.hlen = 6;
+ data.plen = 4;
+
+ data.opcode = htons(0x0001);
+ get_mac_address(data.srchw);
+ memcpy(data.srcpr, ip_address, sizeof(uint8_t[4]));
+
+ memset(data.dsthw, 0, sizeof(uint8_t[6]));
+ memcpy(data.dstpr, ip, sizeof(uint8_t[4]));
+
+ uint8_t broadcast[6];
+ memset(broadcast, 0xFF, sizeof(broadcast));
+ send_ethernet_packet(broadcast, 0x0806, (uint8_t *)&data, sizeof(data));
+}
+
+int get_mac_from_ip(const uint8_t ip[4], uint8_t mac[6]) {
+ print_ip("ARP GETTING MAC FROM IP: ", ip);
+ for (int i = 0; i < 10; i++) {
+ if (0 != memcmp(arp_table[i].ip, ip, sizeof(uint8_t[4])))
+ continue;
+ memcpy(mac, arp_table[i].mac, sizeof(uint8_t[6]));
+ return 1;
+ }
+ klog("ARP cache miss", LOG_NOTE);
+ asm("sti");
+ send_arp_request(ip);
+ // TODO: Maybe wait a bit?
+ for (int i = 0; i < 10; i++) {
+ if (0 != memcmp(arp_table[i].ip, ip, sizeof(uint8_t[4])))
+ continue;
+ memcpy(mac, arp_table[i].mac, sizeof(uint8_t[6]));
+ return 1;
+ }
+ assert(0);
+ return 0;
+}
+
void handle_arp(const uint8_t *payload) {
struct ARP_DATA *data = (struct ARP_DATA *)payload;
// Assert that communication is over ethernet
assert(1 == ntohs(data->htype));
- // Assert it is a request
- assert(0x0001 == ntohs(data->opcode));
// Assert that request uses IP
assert(0x0800 == ntohs(data->ptype));
assert(6 == data->hlen);
assert(4 == data->plen);
- print_mac("srchw: ", data->srchw);
- print_ip("srcpr: ", data->srcpr);
+ // Assert it is a request
+ if (0x0001 /*arp_request*/ == ntohs(data->opcode)) {
+ print_mac("srchw: ", data->srchw);
+ print_ip("srcpr: ", data->srcpr);
- print_mac("dsthw: ", data->dsthw);
- print_ip("dstpr: ", data->dstpr);
+ print_mac("dsthw: ", data->dsthw);
+ print_ip("dstpr: ", data->dstpr);
- uint8_t mac[6];
- get_mac_address(mac);
- print_mac("THIS DEVICE MAC: ", mac);
- assert(0 == memcmp(data->dstpr, ip_address, sizeof(uint8_t[4])));
-
- // Now we have to construct a ARP response
- struct ARP_DATA response;
- response.htype = htons(1);
- response.ptype = htons(0x0800);
- response.opcode = htons(0x00002);
- response.hlen = 6;
- response.plen = 4;
- get_mac_address(response.srchw);
- memcpy(response.srcpr, ip_address, sizeof(uint8_t[4]));
-
- memcpy(response.dsthw, data->srchw, sizeof(uint8_t[6]));
- memcpy(response.dstpr, data->srcpr, sizeof(uint8_t[4]));
-
- send_ethernet_packet(data->srchw, 0x0806, (uint8_t *)&response,
- sizeof(response));
+ assert(0 == memcmp(data->dstpr, ip_address, sizeof(uint8_t[4])));
+
+ // Now we have to construct a ARP response
+ struct ARP_DATA response;
+ response.htype = htons(1);
+ response.ptype = htons(0x0800);
+ response.opcode = htons(0x00002);
+ response.hlen = 6;
+ response.plen = 4;
+ get_mac_address(response.srchw);
+ memcpy(response.srcpr, ip_address, sizeof(uint8_t[4]));
+
+ memcpy(response.dsthw, data->srchw, sizeof(uint8_t[6]));
+ memcpy(response.dstpr, data->srcpr, sizeof(uint8_t[4]));
+
+ send_ethernet_packet(data->srchw, 0x0806, (uint8_t *)&response,
+ sizeof(response));
+ } else if (0x0002 /*arp_response*/ == ntohs(data->opcode)) {
+ // Find a entry to fill
+ struct ARP_TABLE_ENTRY *entry = find_arp_entry_to_use();
+ entry->is_used = 1;
+ memcpy(entry->mac, data->srchw, sizeof(uint8_t[6]));
+ memcpy(entry->ip, data->srcpr, sizeof(uint8_t[4]));
+ print_ip("Added ip: ", entry->ip);
+ } else {
+ kprintf("GOT A ARP REQEUST WITH TYPE: %x\n", ntohs(data->opcode));
+ assert(0);
+ }
}