summaryrefslogtreecommitdiff
path: root/src/user/app/netstack/arp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/user/app/netstack/arp.c')
-rw-r--r--src/user/app/netstack/arp.c56
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);
+}