diff options
Diffstat (limited to 'src/user/app/netstack/arp.c')
-rw-r--r-- | src/user/app/netstack/arp.c | 56 |
1 files changed, 55 insertions, 1 deletions
diff --git a/src/user/app/netstack/arp.c b/src/user/app/netstack/arp.c index 9eab8e3..b43b7e8 100644 --- a/src/user/app/netstack/arp.c +++ b/src/user/app/netstack/arp.c @@ -1,5 +1,7 @@ #include "proto.h" #include "util.h" +#include <assert.h> +#include <camellia/syscalls.h> #include <string.h> enum { @@ -13,8 +15,16 @@ enum { OpReply = 2, }; +struct arpc { + struct arpc *next; + uint32_t ip; + mac_t mac; +}; +static struct arpc *arpcache; +static void arpcache_put(uint32_t ip, mac_t mac); + void arp_parse(const uint8_t *buf, size_t len) { - // TODO no bound checks + if (len < Operation + 2) return; uint16_t htype = nget16(buf + HdrType); uint16_t ptype = nget16(buf + ProtoType); uint16_t op = nget16(buf + Operation); @@ -26,6 +36,8 @@ void arp_parse(const uint8_t *buf, size_t len) { DstMAC = 18, DstIP = 24, }; + if (len < DstIP + 4) return; + arpcache_put(nget32(buf + SrcIP), *(mac_t*)buf + SrcMAC); if (op == OpReq) { uint32_t daddr = nget32(buf + DstIP); @@ -46,3 +58,45 @@ void arp_parse(const uint8_t *buf, size_t len) { } } } + +static void arpcache_put(uint32_t ip, mac_t mac) { + for (struct arpc *iter = arpcache; iter; iter = iter->next) { + if (memcmp(iter->mac, mac, 6) == 0) { + if (iter->ip == ip) return; /* cache entry correct */ + else break; /* cache entry needs updating */ + } + } + struct arpc *e = malloc(sizeof *e); + e->next = arpcache; + e->ip = ip; + memcpy(e->mac, mac, 6); + arpcache = e; +} + +void arp_fsread(handle_t h, long offset) { + const char *fmt = "%08x\t%02x:%02x:%02x:%02x:%02x:%02x\n"; + long linelen = snprintf(NULL, 0, fmt, 0, 1, 2, 3, 4, 5, 6) + 1; + char buf[28]; + assert(linelen <= (long)sizeof(buf)); + if (offset < 0) goto err; + + struct arpc *cur = arpcache; + if (!cur) goto err; + for (; linelen <= offset; offset -= linelen) { + cur = cur->next; + if (!cur) goto err; + } + assert(0 <= offset && offset < linelen); + + snprintf(buf, sizeof buf, fmt, cur->ip, + cur->mac[0], + cur->mac[1], + cur->mac[2], + cur->mac[3], + cur->mac[4], + cur->mac[5]); + _syscall_fs_respond(h, buf + offset, linelen - offset, 0); + return; +err: + _syscall_fs_respond(h, NULL, -1, 0); +} |