diff options
| author | Miguel <m.i@gmx.at> | 2018-09-25 12:43:03 +0200 |
|---|---|---|
| committer | Miguel <m.i@gmx.at> | 2018-09-25 12:43:03 +0200 |
| commit | 112ca29a3bb2ab38693943ed33ee51f4fd7d2d81 (patch) | |
| tree | c843051f9291ebe2de6e603c45d924d843d35ea4 /net/arp.c | |
| parent | 2ba77c01a33c3454aeed42d5394dd5ccede10851 (diff) | |
arp replies working!
Diffstat (limited to 'net/arp.c')
| -rw-r--r-- | net/arp.c | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/net/arp.c b/net/arp.c new file mode 100644 index 0000000..501186f --- /dev/null +++ b/net/arp.c @@ -0,0 +1,126 @@ +// https://github.com/saminiir/level-ip/blob/e9ceb08f01a5499b85f03e2d615309c655b97e8f/src/arp.c#L53 +// https://github.com/chobits/tapip +// https://tools.ietf.org/html/rfc826 + +#include "inet.h" +#include "eth.h" +#include "arp.h" +#include "netdev.h" +#include "log.h" + +#include "lib/string/string.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); + + 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: + arp_reply(netdev, hdr, arphdr); + break; + default: + klog("Opcode not supported\n"); + break; + } +} |
