summaryrefslogtreecommitdiff
path: root/src/user
diff options
context:
space:
mode:
Diffstat (limited to 'src/user')
-rw-r--r--src/user/app/netstack/arp.c56
-rw-r--r--src/user/app/netstack/fs.c13
-rw-r--r--src/user/app/netstack/proto.h1
3 files changed, 68 insertions, 2 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);
+}
diff --git a/src/user/app/netstack/fs.c b/src/user/app/netstack/fs.c
index 52d6038..dc6db04 100644
--- a/src/user/app/netstack/fs.c
+++ b/src/user/app/netstack/fs.c
@@ -2,6 +2,8 @@
* path format:
* /net/raw
* raw ethernet frames (read-write)
+ * /net/arp
+ * ARP cache (currently read-only)
* /net/0.0.0.0/connect/1.2.3.4/udp/53
* connect from 0.0.0.0 (any ip) to 1.2.3.4 on udp port 53
* /net/0.0.0.0/listen/udp/53
@@ -9,6 +11,7 @@
* open() returns once a connection to ip 0.0.0.0 on udp port 53 is received
*/
#include "proto.h"
+#include "util.h"
#include <camellia/syscalls.h>
#include <stdio.h>
#include <stdlib.h>
@@ -17,6 +20,7 @@
enum handle_type {
H_ETHER,
H_UDP,
+ H_ARP,
};
struct strqueue {
@@ -79,7 +83,7 @@ static void udp_recv_enqueue(struct handle *h, handle_t reqh) {
}
static void fs_open(handle_t reqh, char *path) {
-#define respond(buf, val) do{ _syscall_fs_respond(reqh, NULL, -1, 0); return; }while(0)
+#define respond(buf, val) do{ _syscall_fs_respond(reqh, buf, val, 0); return; }while(0)
struct handle *h;
if (*path != '/') respond(NULL, -1);
path++;
@@ -88,6 +92,10 @@ static void fs_open(handle_t reqh, char *path) {
h = malloc(sizeof *h);
h->type = H_ETHER;
respond(h, 0);
+ } else if (strcmp(path, "arp") == 0) {
+ h = malloc(sizeof *h);
+ h->type = H_ARP;
+ respond(h, 0);
}
char *save;
@@ -147,6 +155,9 @@ void fs_thread(void *arg) { (void)arg;
case H_UDP:
udp_recv_enqueue(h, reqh);
break;
+ case H_ARP:
+ arp_fsread(reqh, res.offset);
+ break;
default:
_syscall_fs_respond(reqh, NULL, -1, 0);
}
diff --git a/src/user/app/netstack/proto.h b/src/user/app/netstack/proto.h
index 106f286..864f1c1 100644
--- a/src/user/app/netstack/proto.h
+++ b/src/user/app/netstack/proto.h
@@ -46,6 +46,7 @@ struct ethq {
extern struct ethq *ether_queue;
void arp_parse(const uint8_t *buf, size_t len);
+void arp_fsread(handle_t h, long offset);
void icmp_parse(const uint8_t *buf, size_t len, struct ipv4 ip);
void icmp_send(const void *payload, size_t len, struct icmp i);