diff options
author | dzwdz | 2022-08-20 11:11:57 +0200 |
---|---|---|
committer | dzwdz | 2022-08-20 11:11:57 +0200 |
commit | f22f019aeba00ccb3cc35fe763c3e87bf5690040 (patch) | |
tree | 6f7338b526dca6eebc865096dbdbd3af90cda335 | |
parent | 2a16c1f6f9118e7127d532421ae19b959b3f1d87 (diff) |
user/ethdump: turn into a file server
-rw-r--r-- | initrd/arp.ether | bin | 0 -> 64 bytes | |||
-rw-r--r-- | src/user/app/ethdump/arp.c | 8 | ||||
-rw-r--r-- | src/user/app/ethdump/ethdump.c | 27 | ||||
-rw-r--r-- | src/user/app/ethdump/ether.c | 37 | ||||
-rw-r--r-- | src/user/app/ethdump/fs.c | 65 | ||||
-rw-r--r-- | src/user/app/ethdump/icmp.c | 2 | ||||
-rw-r--r-- | src/user/app/ethdump/ipv4.c | 32 | ||||
-rw-r--r-- | src/user/app/ethdump/proto.h | 9 | ||||
-rw-r--r-- | src/user/app/ethdump/util.c | 14 | ||||
-rw-r--r-- | src/user/app/ethdump/util.h | 5 | ||||
-rw-r--r-- | src/user/app/init/init.c | 4 | ||||
-rw-r--r-- | src/user/app/shell/builtins.c | 2 |
12 files changed, 119 insertions, 86 deletions
diff --git a/initrd/arp.ether b/initrd/arp.ether Binary files differnew file mode 100644 index 0000000..c8fbec7 --- /dev/null +++ b/initrd/arp.ether diff --git a/src/user/app/ethdump/arp.c b/src/user/app/ethdump/arp.c index a022b12..cfb1e04 100644 --- a/src/user/app/ethdump/arp.c +++ b/src/user/app/ethdump/arp.c @@ -1,6 +1,5 @@ #include "proto.h" #include "util.h" -#include <stdlib.h> #include <string.h> enum { @@ -20,12 +19,6 @@ void arp_parse(const uint8_t *buf, size_t len) { uint16_t ptype = nget16(buf + ProtoType); uint16_t op = nget16(buf + Operation); - const char *ops = "bad operation"; - if (op == 1) ops = "request"; - if (op == 2) ops = "reply"; - - printf("ARP htype 0x%x, ptype 0x%x, %s\n", htype, ptype, ops); - if (!(htype == HdrTypeEther && ptype == ET_IPv4)) return; enum { /* only valid for this combination of header + proto */ SrcMAC = 8, @@ -36,7 +29,6 @@ void arp_parse(const uint8_t *buf, size_t len) { if (op == OpReq) { uint32_t daddr = nget32(buf + DstIP); - printf("IPv4 request for %08x\n", daddr); if (daddr == state.ip) { uint8_t *pkt = ether_start(30, (struct ethernet){ .dst = buf + SrcMAC, diff --git a/src/user/app/ethdump/ethdump.c b/src/user/app/ethdump/ethdump.c index 4047962..17592a1 100644 --- a/src/user/app/ethdump/ethdump.c +++ b/src/user/app/ethdump/ethdump.c @@ -5,6 +5,7 @@ #include <stddef.h> #include <stdlib.h> #include <string.h> +#include <user/lib/thread.h> struct net_state state = { // TODO dynamically get mac @@ -12,23 +13,29 @@ struct net_state state = { .ip = (192 << 24) + (168 << 16) + 11, }; -int main(void) { - const char *path = "/kdev/eth"; - state.raw_h = _syscall_open(path, strlen(path), 0); - if (state.raw_h < 0) { - eprintf("couldn't open %s", path); - return 1; - } - +void network_thread(void *arg) { (void)arg; const size_t buflen = 4096; char *buf = malloc(buflen); for (;;) { long ret = _syscall_read(state.raw_h, buf, buflen, -1); if (ret < 0) break; - printf("\npacket of length %u\n", ret); - hexdump(buf, ret); ether_parse((void*)buf, ret); } free(buf); +} + +void fs_thread(void *arg); + +int main(void) { + const char *path = "/kdev/eth"; + state.raw_h = _syscall_open(path, strlen(path), 0); + if (state.raw_h < 0) { + eprintf("couldn't open %s", path); + return 1; + } + + thread_create(0, network_thread, NULL); + thread_create(0, fs_thread, NULL); + _syscall_await(); return 0; } diff --git a/src/user/app/ethdump/ether.c b/src/user/app/ethdump/ether.c index 32646e2..3f6a40d 100644 --- a/src/user/app/ethdump/ether.c +++ b/src/user/app/ethdump/ether.c @@ -10,37 +10,32 @@ enum { EtherType = 12, Payload = 14, }; +struct queue_entry *ether_queue; void ether_parse(const uint8_t *buf, size_t len) { - uint8_t dmac[6], smac[6]; - - if (len < 60) return; - for (int i = 0; i < 6; i++) dmac[i] = buf[i + DstMAC]; - for (int i = 0; i < 6; i++) smac[i] = buf[i + SrcMAC]; - printf("from %02x:%02x:%02x:%02x:%02x:%02x\n", - smac[0], smac[1], smac[2], smac[3], smac[4], smac[5]); - printf("to %02x:%02x:%02x:%02x:%02x:%02x\n", - dmac[0], dmac[1], dmac[2], dmac[3], dmac[4], dmac[5]); - - uint16_t ethertype = nget16(buf + EtherType); - printf("ethertype %u\n", ethertype); - struct ethernet ether = (struct ethernet){ - .src = &smac, - .dst = &dmac, - .type = ethertype, + .src = buf + SrcMAC, + .dst = buf + DstMAC, + .type = nget16(buf + EtherType), }; - switch (ethertype) { + struct queue_entry **iter = ðer_queue; + while (iter && *iter) { + struct queue_entry *qe = *iter; + _syscall_fs_respond(qe->h, buf, len, 0); + /* remove entry */ + /* yes, doing it this way here doesn't make sense. i'm preparing for filtering */ + *iter = qe->next; + free(qe); + } + + switch (ether.type) { case ET_IPv4: ipv4_parse(buf + Payload, len - Payload, ether); break; case ET_ARP: arp_parse(buf + Payload, len - Payload); break; - default: - printf("(unknown)\n"); - break; } } @@ -62,8 +57,6 @@ uint8_t *ether_start(size_t len, struct ethernet ether) { void ether_finish(uint8_t *pkt) { uint8_t *buf = pkt - Payload - fhoff; size_t len = *(size_t*)buf; - printf("sending:\n"); - hexdump(buf + fhoff, len); _syscall_write(state.raw_h, buf + fhoff, len, 0, 0); free(buf); } diff --git a/src/user/app/ethdump/fs.c b/src/user/app/ethdump/fs.c new file mode 100644 index 0000000..5078a13 --- /dev/null +++ b/src/user/app/ethdump/fs.c @@ -0,0 +1,65 @@ +#include "proto.h" +#include <camellia/syscalls.h> +#include <stdlib.h> +#include <string.h> +#include <user/lib/fs/dir.h> + +enum { + H_ROOT, + H_ETHER, +}; + +void fs_thread(void *arg) { (void)arg; + const size_t buflen = 4096; + char *buf = malloc(buflen); + for (;;) { + struct fs_wait_response res; + handle_t h = _syscall_fs_wait(buf, buflen, &res); + if (h < 0) break; + switch (res.op) { + long ret; + case VFSOP_OPEN: + ret = -1; + if (res.len < buflen) { + buf[res.len] = '\0'; + if (!strcmp("/", buf)) ret = H_ROOT; + else if (!strcmp("/raw", buf)) ret = H_ETHER; + } + _syscall_fs_respond(h, (void*)ret, ret, 0); + break; + case VFSOP_READ: + switch ((long)res.id) { + struct dirbuild db; + struct queue_entry *qe; + case H_ROOT: + dir_start(&db, res.offset, buf, sizeof buf); + dir_append(&db, "raw"); + _syscall_fs_respond(h, buf, dir_finish(&db), 0); + break; + case H_ETHER: + qe = malloc(sizeof *qe); + qe->h = h; + qe->next = ether_queue; + ether_queue = qe; + break; + default: + _syscall_fs_respond(h, NULL, -1, 0); + } + break; + case VFSOP_WRITE: + switch ((long)res.id) { + case H_ETHER: + ret = _syscall_write(state.raw_h, buf, res.len, 0, 0); + _syscall_fs_respond(h, NULL, ret, 0); + break; + default: + _syscall_fs_respond(h, NULL, -1, 0); + } + break; + default: + _syscall_fs_respond(h, NULL, -1, 0); + break; + } + } + free(buf); +} diff --git a/src/user/app/ethdump/icmp.c b/src/user/app/ethdump/icmp.c index 3f10ae8..b3eff93 100644 --- a/src/user/app/ethdump/icmp.c +++ b/src/user/app/ethdump/icmp.c @@ -12,8 +12,8 @@ enum { void icmp_parse(const uint8_t *buf, size_t len, struct ipv4 ip) { if (len < Payload) return; uint8_t type = buf[Type]; - printf("ICMP type %u\n", type); if (type == 8 && ip.dst == state.ip) { + /* echo reply */ uint8_t *pkt = icmp_start(len - Payload, (struct icmp){ .type = 0, .ip.dst = ip.src, diff --git a/src/user/app/ethdump/ipv4.c b/src/user/app/ethdump/ipv4.c index c9b2df4..e8ab7ea 100644 --- a/src/user/app/ethdump/ipv4.c +++ b/src/user/app/ethdump/ipv4.c @@ -15,48 +15,30 @@ enum { }; void ipv4_parse(const uint8_t *buf, size_t len, struct ethernet ether) { - uint8_t version, headerlen, proto; + uint8_t version, headerlen; uint16_t packetlen, id; - uint32_t dst, src; version = buf[Version] >> 4; - if (version != 4) { - printf("bad IPv4 version %u\n", version); - return; - } + if (version != 4) return; headerlen = (buf[HdrLen] & 0xf) * 4; packetlen = nget16(buf + PktLen); + if (packetlen < headerlen) return; id = nget16(buf + Id); - proto = buf[Proto]; - src = nget32(buf + SrcIP); - dst = nget32(buf + DstIP); // TODO checksum // TODO fragmentation - printf("headerlen %u, packetlen %u (real %u), id %u\n", headerlen, packetlen, len, id); - printf("from %x to %x\n", src, dst); - printf("id %u\n", id); - if (packetlen < headerlen) { - printf("headerlen too big\n"); - return; - } - struct ipv4 ip = (struct ipv4){ .e = ether, - .src = src, - .dst = dst, - .proto = proto, + .src = nget32(buf + SrcIP), + .dst = nget32(buf + DstIP), + .proto = buf[Proto], }; - switch (proto) { + switch (ip.proto) { case 1: - printf("proto %u - icmp\n", proto); icmp_parse(buf + headerlen, packetlen - headerlen, ip); break; - default: - printf("proto %u - unknown\n", proto); - break; } } diff --git a/src/user/app/ethdump/proto.h b/src/user/app/ethdump/proto.h index df2000e..21057a2 100644 --- a/src/user/app/ethdump/proto.h +++ b/src/user/app/ethdump/proto.h @@ -34,6 +34,15 @@ struct icmp { }; +/* NOT THREADSAFE, YET USED FROM THREADS + * will break if i implement a scheduler*/ +struct queue_entry { + handle_t h; + struct queue_entry *next; +}; +extern struct queue_entry *ether_queue; + + void arp_parse(const uint8_t *buf, size_t len); void icmp_parse(const uint8_t *buf, size_t len, struct ipv4 ip); diff --git a/src/user/app/ethdump/util.c b/src/user/app/ethdump/util.c index 8c29340..7c484f3 100644 --- a/src/user/app/ethdump/util.c +++ b/src/user/app/ethdump/util.c @@ -1,19 +1,5 @@ #include "util.h" -void hexdump(const void *vbuf, size_t len) { - const uint8_t *buf = vbuf; - for (size_t i = 0; i < len; i += 16) { - printf("%08x ", i); - - for (size_t j = i; j < i + 8 && j < len; j++) - printf("%02x ", buf[j]); - printf(" "); - for (size_t j = i + 8; j < i + 16 && j < len; j++) - printf("%02x ", buf[j]); - printf("\n"); - } -} - /* https://www.w3.org/TR/PNG/#D-CRCAppendix */ static uint32_t crc_table[256]; uint32_t crc32(const uint8_t *buf, size_t len) { diff --git a/src/user/app/ethdump/util.h b/src/user/app/ethdump/util.h index ca7e99b..6f58b82 100644 --- a/src/user/app/ethdump/util.h +++ b/src/user/app/ethdump/util.h @@ -4,14 +4,9 @@ #define eprintf(fmt, ...) fprintf(stderr, "ethdump: "fmt"\n" __VA_OPT__(,) __VA_ARGS__) -// #define printf(...) - -void hexdump(const void *vbuf, size_t len); - uint32_t crc32(const uint8_t *buf, size_t len); uint16_t ip_checksum(const uint8_t *buf, size_t len); - static inline void nput16(void *vbuf, uint16_t n) { uint8_t *b = vbuf; b[0] = n >> 8; diff --git a/src/user/app/init/init.c b/src/user/app/init/init.c index 49cc085..acf9b03 100644 --- a/src/user/app/init/init.c +++ b/src/user/app/init/init.c @@ -67,6 +67,10 @@ int main(void) { const char *argv[] = {"/bin/vterm", NULL}; execv(argv[0], (void*)argv); } + MOUNT_AT("/net/") { + const char *argv[] = {"/bin/ethdump", NULL}; + execv(argv[0], (void*)argv); + } if (_syscall_pipe(killswitch_pipe, 0) < 0) { printf("couldn't create the killswitch pipe, quitting...\n"); diff --git a/src/user/app/shell/builtins.c b/src/user/app/shell/builtins.c index 23a8221..1be9b5b 100644 --- a/src/user/app/shell/builtins.c +++ b/src/user/app/shell/builtins.c @@ -28,7 +28,7 @@ static void cmd_cat(int argc, char **argv) { } if (!strcmp(argv[i], "!stdin")) fextflags(file, FEXT_NOFILL); for (;;) { - int len = fread(buf, 1, sizeof buf, file); + int len = fread(buf, 1, buflen, file); if (len <= 0) break; fwrite(buf, 1, len, stdout); } |