Orion
Barry Importing existing Orion kernel d41a53c (2 years, 4 months ago)/* * This file contains the implementation of ARP for the Network Stack. It * handles converting IP addresses to MAC addresses, and sits between the * Network layer and the Ethernet layer. */ #include <stdint.h> #include <stddef.h> #include <string.h> #include "net.h" #include "../mem/heap.h" #include "../screen.h" typedef struct ARPCacheEntry ARPCacheEntry; /* Structure for an ARP Cache Entry */ struct ARPCacheEntry { uint8_t mac[6], ip[4]; ARPCacheEntry *next; }; /* Structure for an ARP Packet */ typedef struct Packet { uint16_t hardwareType; uint16_t protocolType; uint8_t hardwareSize; uint8_t protocolSize; uint16_t opcode; uint8_t srcMac[6], srcIp[4]; uint8_t dstMac[6], dstIp[4]; } __attribute__((packed)) Packet; ARPCacheEntry *arpCache; /* Request a MAC address from IP with ARP */ void arp_request(NetIF *netif, uint8_t dstIp[4], uint8_t *res) { uint8_t dstMac[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; Packet packet = { .hardwareType = htons(netif->type), .protocolType = htons(0x0800), /* EtherType IPv4 */ .hardwareSize = 6, .protocolSize = 4, .opcode = htons(0x0001), /* ARP Request */ }; memcpy(packet.srcMac, netif->mac, 6); memcpy(packet.srcIp, netif->ip, 4); memcpy(packet.dstMac, dstMac, 6); memcpy(packet.dstIp, dstIp, 4); ethernet_send_frame(netif, dstMac, 0x0806, &packet, sizeof(Packet)); if (!res) return; /* Wait for result */ ARPCacheEntry *ce; search: for (ce = arpCache; ce; ce = ce->next) if (!memcmp(ce->ip, dstIp, 4)) break; if (!ce) goto search; memcpy(res, ce->mac, 6); } /* Reply to an ARP Request */ void arp_reply(NetIF *netif, Packet *request) { Packet reply = { .hardwareType = htons(netif->type), .hardwareSize = request->hardwareSize, .protocolType = htons(request->protocolType), .protocolSize = request->protocolSize, .opcode = htons(0x0002), /* ARP Reply */ }; memcpy(reply.srcMac, netif->mac, 6); memcpy(reply.srcIp, netif->ip, 4); memcpy(reply.dstMac, request->srcMac, 6); memcpy(reply.dstIp, request->srcIp, 4); ethernet_send_frame(netif, request->srcMac, 0x0806, &reply, sizeof(Packet)); } /* Handle an incoming ARP packet */ void arp_receive_packet(NetIF *netif, void *data, size_t len) { Packet packet; memcpy(&packet, data, sizeof(Packet)); packet.hardwareType = ntohs(packet.hardwareType); packet.protocolType = ntohs(packet.protocolType); packet.opcode = ntohs(packet.opcode); switch (packet.opcode) { case 0x0001: /* ARP Request */ if (!memcmp(packet.dstIp, netif->ip, 4)) arp_reply(netif, &packet); /* FALLTHROUGH */ case 0x0002: /* ARP Reply */ ARPCacheEntry *ce; for (ce = arpCache; ce; ce = ce->next) if (!memcmp(ce->ip, packet.srcIp, 4)) break; if (ce) { memcpy(ce->mac, packet.srcMac, 6); break; } ce = kmalloc(sizeof(ARPCacheEntry)); memcpy(ce->mac, packet.srcMac, 6); memcpy(ce->ip, packet.srcIp, 4); ce->next = arpCache; arpCache = ce; break; } }