summaryrefslogtreecommitdiff
path: root/src/user/app/netstack
diff options
context:
space:
mode:
Diffstat (limited to 'src/user/app/netstack')
-rw-r--r--src/user/app/netstack/arp.c151
-rw-r--r--src/user/app/netstack/ether.c59
-rw-r--r--src/user/app/netstack/fs.c320
-rw-r--r--src/user/app/netstack/icmp.c34
-rw-r--r--src/user/app/netstack/ipv4.c216
-rw-r--r--src/user/app/netstack/netstack.c53
-rw-r--r--src/user/app/netstack/proto.h107
-rw-r--r--src/user/app/netstack/tcp.c268
-rw-r--r--src/user/app/netstack/udp.c124
-rw-r--r--src/user/app/netstack/util.c60
-rw-r--r--src/user/app/netstack/util.h44
11 files changed, 0 insertions, 1436 deletions
diff --git a/src/user/app/netstack/arp.c b/src/user/app/netstack/arp.c
deleted file mode 100644
index 3a1c8da..0000000
--- a/src/user/app/netstack/arp.c
+++ /dev/null
@@ -1,151 +0,0 @@
-#include "proto.h"
-#include "util.h"
-#include <assert.h>
-#include <camellia/syscalls.h>
-#include <string.h>
-
-enum {
- HdrType = 0,
- HdrTypeEther = 1,
- ProtoType = 2,
- HdrALen = 4,
- ProtoALen = 5,
- Operation = 6,
- OpReq = 1,
- 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) {
- if (len < Operation + 2) return;
- uint16_t htype = nget16(buf + HdrType);
- uint16_t ptype = nget16(buf + ProtoType);
- uint16_t op = nget16(buf + Operation);
-
- if (!(htype == HdrTypeEther && ptype == ET_IPv4)) return;
- enum { /* only valid for this combination of header + proto */
- SrcMAC = 8,
- SrcIP = 14,
- 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);
- if (daddr == state.ip) {
- uint8_t *pkt = ether_start(30, (struct ethernet){
- .dst = (void*)(buf + SrcMAC),
- .type = ET_ARP,
- });
- nput16(pkt + HdrType, HdrTypeEther);
- nput16(pkt + ProtoType, ET_IPv4);
- pkt[HdrALen] = 6;
- pkt[ProtoALen] = 4;
- nput16(pkt + Operation, OpReply);
- memcpy(pkt + SrcMAC, state.mac, 6);
- nput32(pkt + SrcIP, state.ip);
- memcpy(pkt + DstMAC, buf + SrcMAC, 10); /* sender's MAC and IP */
- ether_finish(pkt);
- }
- }
-}
-
-void arp_request(uint32_t ip) {
- enum {
- SrcMAC = 8,
- SrcIP = 14,
- DstMAC = 18,
- DstIP = 24,
- };
- uint8_t *pkt = ether_start(28, (struct ethernet){
- .src = &state.mac,
- .dst = &MAC_BROADCAST,
- .type = ET_ARP,
- });
- nput16(pkt + HdrType, HdrTypeEther);
- nput16(pkt + ProtoType, ET_IPv4);
- pkt[HdrALen] = 6;
- pkt[ProtoALen] = 4;
- nput16(pkt + Operation, OpReq);
- memcpy(pkt + SrcMAC, state.mac, 6);
- nput32(pkt + SrcIP, state.ip);
- memcpy(pkt + DstMAC, &MAC_BROADCAST, 6);
- nput32(pkt + DstIP, ip);
- ether_finish(pkt);
-}
-
-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;
-}
-
-int arpcache_get(uint32_t ip, mac_t *mac) {
- for (struct arpc *iter = arpcache; iter; iter = iter->next) {
- if (iter->ip == ip) {
- if (mac) memcpy(mac, iter->mac, 6);
- return 0;
- }
- }
- return -1;
-}
-
-void arp_fsread(hid_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]);
- _sys_fs_respond(h, buf + offset, linelen - offset, 0);
- return;
-err:
- _sys_fs_respond(h, NULL, -1, 0);
-}
-
-long arp_fswrite(const char *buf, long len, long offset) {
- if (offset != -1) return -1;
- uint32_t ip;
- char tmp[16];
- size_t iplen = len < 15 ? len : 15;
- memcpy(tmp, buf, iplen);
- tmp[iplen] = '\0';
- if (ip_parse(tmp, &ip) < 0) {
- return -1;
- } else {
- arp_request(ip);
- return len;
- }
-}
diff --git a/src/user/app/netstack/ether.c b/src/user/app/netstack/ether.c
deleted file mode 100644
index 52abac2..0000000
--- a/src/user/app/netstack/ether.c
+++ /dev/null
@@ -1,59 +0,0 @@
-#include <camellia/syscalls.h>
-#include "proto.h"
-#include "util.h"
-
-enum {
- DstMAC = 0,
- SrcMAC = 6,
- EtherType = 12,
- Payload = 14,
-};
-struct ethq *ether_queue;
-
-void ether_parse(const uint8_t *buf, size_t len) {
- struct ethernet ether = (struct ethernet){
- .src = (void*)(buf + SrcMAC),
- .dst = (void*)(buf + DstMAC),
- .type = nget16(buf + EtherType),
- };
-
- for (struct ethq **iter = &ether_queue; iter && *iter; ) {
- struct ethq *qe = *iter;
- _sys_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;
- }
-}
-
-static const size_t fhoff = sizeof(size_t);
-uint8_t *ether_start(size_t len, struct ethernet ether) {
- if (len < 60 - Payload) len = 60 - Payload;
-
- if (!ether.dst) eprintf("NULL ether.dst!"); // TODO arp? i guess?
- if (!ether.src) ether.src = &state.mac;
-
- uint8_t *buf = malloc(fhoff + Payload + len);
- memset(buf, 0, fhoff + Payload + len);
- *(size_t*)buf = len + Payload;
- memcpy(buf + fhoff + DstMAC, ether.dst, 6);
- memcpy(buf + fhoff + SrcMAC, ether.src, 6);
- nput16(buf + fhoff + EtherType, ether.type);
- return buf + fhoff + Payload;
-}
-void ether_finish(uint8_t *pkt) {
- uint8_t *buf = pkt - Payload - fhoff;
- size_t len = *(size_t*)buf;
- _sys_write(state.raw_h, buf + fhoff, len, 0, 0);
- free(buf);
-}
diff --git a/src/user/app/netstack/fs.c b/src/user/app/netstack/fs.c
deleted file mode 100644
index 6d51c35..0000000
--- a/src/user/app/netstack/fs.c
+++ /dev/null
@@ -1,320 +0,0 @@
-/*
- * path format:
- * /net/raw
- * raw ethernet frames (read-write)
- * /net/arp
- * ARP cache (currently read-only)
- * /net/connect/0.0.0.0/1.2.3.4/udp/53
- * connect from 0.0.0.0 (any ip) to 1.2.3.4 on udp port 53
- * /net/listen/0.0.0.0/{tcp,udp}/53
- * waits for a connection to any ip on udp port 53
- * 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/flags.h>
-#include <camellia/syscalls.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-enum handle_type {
- H_ETHER,
- H_TCP,
- H_UDP,
- H_ARP,
-};
-
-struct strqueue {
- struct strqueue *next;
- size_t len;
- char buf[];
-};
-
-struct handle {
- enum handle_type type;
- struct {
- struct udp_conn *c;
- struct strqueue *rx, *rxlast;
- } udp;
- struct {
- struct tcp_conn *c;
- size_t readcap;
- } tcp;
- bool dead;
- hid_t reqh;
-};
-
-
-static void tcp_listen_callback(struct tcp_conn *c, void *arg) {
- struct handle *h = arg;
- h->tcp.c = c;
- _sys_fs_respond(h->reqh, h, 0, 0);
- h->reqh = -1;
-}
-
-/* also called from recv_enqueue. yes, it's a mess */
-static void tcp_recv_callback(void *arg) {
- struct handle *h = arg;
- char buf[1024];
- if (h->reqh >= 0) {
- if (h->tcp.readcap > sizeof buf)
- h->tcp.readcap = sizeof buf;
- size_t len = tcpc_tryread(h->tcp.c, buf, h->tcp.readcap);
- if (len > 0) {
- _sys_fs_respond(h->reqh, buf, len, 0);
- h->reqh = -1;
- }
- }
-}
-
-static void tcp_close_callback(void *arg) {
- struct handle *h = arg;
- h->dead = true;
- if (h->reqh >= 0) {
- _sys_fs_respond(h->reqh, NULL, -ECONNRESET, 0);
- h->reqh = -1;
- return;
- }
-}
-
-static void udp_listen_callback(struct udp_conn *c, void *arg) {
- struct handle *h = arg;
- h->udp.c = c;
- _sys_fs_respond(h->reqh, h, 0, 0);
- h->reqh = -1;
-}
-
-static void udp_recv_callback(const void *buf, size_t len, void *arg) {
- struct handle *h = arg;
- if (h->reqh >= 0) {
- _sys_fs_respond(h->reqh, buf, len, 0);
- h->reqh = -1;
- return;
- }
- struct strqueue *sq = malloc(sizeof(*sq) + len);
- sq->next = NULL;
- sq->len = len;
- memcpy(sq->buf, buf, len);
- if (h->udp.rx) {
- h->udp.rxlast->next = sq;
- h->udp.rxlast = sq;
- } else {
- h->udp.rx = sq;
- h->udp.rxlast = sq;
- }
-}
-
-static void recv_enqueue(struct handle *h, hid_t reqh, size_t readcap) {
- if (h->reqh > 0) {
- // TODO queue
- _sys_fs_respond(reqh, NULL, -1, 0);
- return;
- }
- if (h->type == H_UDP && h->udp.rx) {
- _sys_fs_respond(reqh, h->udp.rx->buf, h->udp.rx->len, 0);
- h->udp.rx = h->udp.rx->next;
- free(h->udp.rx);
- return;
- }
- h->reqh = reqh;
- if (h->type == H_TCP) {
- h->tcp.readcap = readcap;
- tcp_recv_callback(h);
- }
-}
-
-static void fs_open(hid_t reqh, char *path, int flags) {
-#define respond(buf, val) do{ _sys_fs_respond(reqh, buf, val, 0); return; }while(0)
- struct handle *h;
- if (*path != '/') respond(NULL, -1);
- path++;
-
- if (strcmp(path, "raw") == 0) {
- h = malloc(sizeof *h);
- memset(h, 0, sizeof *h);
- h->type = H_ETHER;
- respond(h, 0);
- } else if (strcmp(path, "arp") == 0) {
- h = malloc(sizeof *h);
- memset(h, 0, sizeof *h);
- h->type = H_ARP;
- respond(h, 0);
- }
-
- /* everything below ends up sending packets */
- if (!OPEN_WRITEABLE(flags))
- respond(NULL, -EACCES);
-
- char *save;
- const char *verb, *proto, *port_s;
- uint32_t srcip, dstip;
-
- verb = strtok_r(path, "/", &save);
- if (!verb) respond(NULL, -1);
-
- if (ip_parse(strtok_r(NULL, "/", &save), &srcip) < 0)
- respond(NULL, -1);
- if (srcip != 0) {
- eprintf("unimplemented");
- respond(NULL, -1);
- }
-
- if (strcmp(verb, "listen") == 0) {
- proto = strtok_r(NULL, "/", &save);
- if (!proto) respond(NULL, -1);
- if (strcmp(proto, "udp") == 0) {
- port_s = strtok_r(NULL, "/", &save);
- if (port_s) {
- uint16_t port = strtol(port_s, NULL, 0);
- h = malloc(sizeof *h);
- memset(h, 0, sizeof *h);
- h->type = H_UDP;
- h->reqh = reqh;
- udp_listen(port, udp_listen_callback, udp_recv_callback, h);
- return;
- }
- }
- if (strcmp(proto, "tcp") == 0) {
- port_s = strtok_r(NULL, "/", &save);
- if (port_s) {
- uint16_t port = strtol(port_s, NULL, 0);
- h = malloc(sizeof *h);
- memset(h, 0, sizeof *h);
- h->type = H_TCP;
- h->reqh = reqh;
- tcp_listen(port, tcp_listen_callback, tcp_recv_callback, tcp_close_callback, h);
- return;
- }
- }
- } else if (strcmp(verb, "connect") == 0) {
- if (ip_parse(strtok_r(NULL, "/", &save), &dstip) < 0)
- respond(NULL, -1);
- proto = strtok_r(NULL, "/", &save);
- if (!proto) respond(NULL, -1);
- if (strcmp(proto, "tcp") == 0) {
- port_s = strtok_r(NULL, "/", &save);
- if (port_s) {
- uint16_t port = strtol(port_s, NULL, 0);
- h = malloc(sizeof *h);
- memset(h, 0, sizeof *h);
- h->type = H_TCP;
- h->tcp.c = tcpc_new((struct tcp){
- .dst = port,
- .ip.dst = dstip,
- }, tcp_recv_callback, tcp_close_callback, h);
- if (h->tcp.c) {
- respond(h, 0);
- } else {
- free(h);
- respond(NULL, -1);
- }
- }
- }
- if (strcmp(proto, "udp") == 0) {
- port_s = strtok_r(NULL, "/", &save);
- if (port_s) {
- uint16_t port = strtol(port_s, NULL, 0);
- h = malloc(sizeof *h);
- memset(h, 0, sizeof *h);
- h->type = H_UDP;
- h->udp.c = udpc_new((struct udp){
- .dst = port,
- .ip.dst = dstip,
- }, udp_recv_callback, h);
- if (h->udp.c) {
- respond(h, 0);
- } else {
- free(h);
- respond(NULL, -1);
- }
- }
- }
- }
- respond(NULL, -1);
-#undef respond
-}
-
-void fs_thread(void *arg) { (void)arg;
- const size_t buflen = 4096;
- char *buf = malloc(buflen);
- for (;;) {
- struct ufs_request res;
- hid_t reqh = _sys_fs_wait(buf, buflen, &res);
- if (reqh < 0) break;
- struct handle *h = res.id;
- long ret;
- switch (res.op) {
- case VFSOP_OPEN:
- if (res.len < buflen) {
- buf[res.len] = '\0';
- fs_open(reqh, buf, res.flags);
- } else {
- _sys_fs_respond(reqh, NULL, -1, 0);
- }
- break;
- case VFSOP_READ:
- if (h->dead) {
- _sys_fs_respond(reqh, NULL, -ECONNRESET, 0);
- break;
- }
- switch (h->type) {
- case H_ETHER: {
- struct ethq *qe;
- qe = malloc(sizeof *qe);
- qe->h = reqh;
- qe->next = ether_queue;
- ether_queue = qe;
- break;}
- case H_TCP:
- case H_UDP:
- recv_enqueue(h, reqh, res.capacity);
- break;
- case H_ARP:
- arp_fsread(reqh, res.offset);
- break;
- default:
- _sys_fs_respond(reqh, NULL, -1, 0);
- }
- break;
- case VFSOP_WRITE:
- if (h->dead) {
- _sys_fs_respond(reqh, NULL, -ECONNRESET, 0);
- break;
- }
- switch (h->type) {
- case H_ETHER:
- ret = _sys_write(state.raw_h, buf, res.len, 0, 0);
- _sys_fs_respond(reqh, NULL, ret, 0);
- break;
- case H_TCP:
- tcpc_send(h->tcp.c, buf, res.len);
- _sys_fs_respond(reqh, NULL, res.len, 0);
- break;
- case H_UDP:
- udpc_send(h->udp.c, buf, res.len);
- _sys_fs_respond(reqh, NULL, res.len, 0);
- break;
- case H_ARP:
- _sys_fs_respond(reqh, NULL, arp_fswrite(buf, res.len, res.offset), 0);
- break;
- default:
- _sys_fs_respond(reqh, NULL, -1, 0);
- }
- break;
- case VFSOP_CLOSE:
- // TODO remove entries in queue
- // TODO why does close even have _sys_fs_respond?
- if (h->type == H_TCP) tcpc_close(h->tcp.c);
- if (h->type == H_UDP) udpc_close(h->udp.c);
- free(h);
- _sys_fs_respond(reqh, NULL, -1, 0);
- break;
- default:
- _sys_fs_respond(reqh, NULL, -1, 0);
- break;
- }
- }
- free(buf);
-}
diff --git a/src/user/app/netstack/icmp.c b/src/user/app/netstack/icmp.c
deleted file mode 100644
index 0c6a502..0000000
--- a/src/user/app/netstack/icmp.c
+++ /dev/null
@@ -1,34 +0,0 @@
-#include "proto.h"
-#include "util.h"
-
-enum {
- Type = 0,
- Code = 1,
- Checksum = 2,
- Payload = 4,
-};
-
-void icmp_parse(const uint8_t *buf, size_t len, struct ipv4 ip) {
- if (len < Payload) return;
- uint8_t type = buf[Type];
- if (type == 8 && ip.dst == state.ip) {
- /* echo reply */
- icmp_send(buf + Payload, len - Payload, (struct icmp){
- .type = 0,
- .ip.dst = ip.src,
- .ip.e.dst = ip.e.src,
- });
- }
-}
-
-void icmp_send(const void *payload, size_t len, struct icmp i) {
- i.ip.proto = 1;
- uint8_t *pkt = malloc(Payload + len);
- pkt[Type] = i.type;
- pkt[Code] = i.code;
- memcpy(pkt + Payload, payload, len);
- nput16(pkt + Checksum, 0);
- nput16(pkt + Checksum, ip_checksum(pkt, Payload + len));
- ipv4_send(pkt, Payload + len, i.ip);
- free(pkt);
-}
diff --git a/src/user/app/netstack/ipv4.c b/src/user/app/netstack/ipv4.c
deleted file mode 100644
index 1336dc1..0000000
--- a/src/user/app/netstack/ipv4.c
+++ /dev/null
@@ -1,216 +0,0 @@
-#include "proto.h"
-#include "util.h"
-#include <assert.h>
-#include <stdlib.h>
-
-enum {
- Version = 0,
- HdrLen = 0,
- TotalLen = 2,
- Id = 4,
- FragInfo = 6,
- EvilBit = 0x8000,
- DontFrag = 0x4000,
- MoreFrags = 0x2000,
- FragOff = 0x1FFF,
- TTL = 8,
- Proto = 9,
- Checksum = 10,
- SrcIP = 12,
- DstIP = 16,
-};
-static void ipv4_dispatch(const uint8_t *buf, size_t len, struct ipv4 ip);
-
-struct fragment {
- struct fragment *next; /* sorted */
- size_t len, offset;
- bool last;
- uint8_t buf[];
-};
-struct fragmented {
- /* src, dst, proto, id come from the first arrived packet
- * and are used to tell fragmenteds apart.
- * the rest comes from the sequentially first packet.
- * ip.h.header points to a malloc'd buffer*/
- struct ipv4 h;
-
- struct fragment *first;
- struct fragmented *next, **prev; /* *(inc->prev) == inc */
- // TODO timer
-};
-struct fragmented *fragmenteds;
-static struct fragmented *fragmented_find(struct ipv4 fraghdr);
-static void fragmented_tryinsert(const uint8_t *payload, size_t plen, struct ipv4 ip);
-static void fragmented_tryfinish(struct fragmented *inc);
-static void fragmented_free(struct fragmented *inc);
-
-static struct fragmented *fragmented_find(struct ipv4 fraghdr) {
- struct fragmented *inc;
- for (inc = fragmenteds; inc; inc = inc->next) {
- if (inc->h.src == fraghdr.src &&
- inc->h.dst == fraghdr.dst &&
- inc->h.proto == fraghdr.proto &&
- inc->h.id == fraghdr.id)
- {
- return inc;
- }
- }
- inc = malloc(sizeof *inc);
- memset(inc, 0, sizeof *inc);
- inc->h.src = fraghdr.src;
- inc->h.dst = fraghdr.dst;
- inc->h.proto = fraghdr.proto;
- inc->h.id = fraghdr.id;
-
- inc->next = fragmenteds;
- if (inc->next) inc->next->prev = &inc->next;
- inc->prev = &fragmenteds;
- *inc->prev = inc;
- return inc;
-}
-
-static void fragmented_tryinsert(const uint8_t *payload, size_t plen, struct ipv4 ip) {
- struct fragmented *inc = fragmented_find(ip);
- size_t off = (ip.fraginfo & FragOff) * 8;
- bool last = !(ip.fraginfo & MoreFrags);
- // eprintf("fragmented packet, %u + %u, part of 0x%x", off, plen, inc);
-
- /* find the first fragment at a bigger offset, and insert before it */
- struct fragment **insert = &inc->first;
- for (; *insert; insert = &(*insert)->next) {
- if ((*insert)->offset > off) break;
- if ((*insert)->offset == off) return; /* duplicate packet */
- }
- /* later on: frag->next = *insert;
- * if we're the last fragment, frag->next must == NULL */
- if (last && *insert != NULL) return;
-
- struct fragment *frag = malloc(sizeof(struct fragment) + plen);
- frag->next = *insert;
- *insert = frag;
- frag->len = plen;
- frag->offset = off;
- frag->last = last;
- memcpy(frag->buf, payload, plen);
-
- if (off == 0) { /* save header */
- assert(!inc->h.header);
- void *headercpy = malloc(ip.hlen);
- memcpy(headercpy, ip.header, ip.hlen);
- inc->h = ip;
- inc->h.header = headercpy;
- }
-
- fragmented_tryfinish(inc);
-}
-
-static void fragmented_tryfinish(struct fragmented *inc) {
- if (inc->first->offset != 0) return;
- for (struct fragment *iter = inc->first; iter; iter = iter->next) {
- size_t iterend = iter->offset + iter->len;
- struct fragment *next = iter->next;
- if (next) {
- if (iterend < next->offset) return; /* incomplete */
- if (iterend > next->offset) {
- fragmented_free(inc);
- return;
- }
- } else if (iter->last) {
- void *buf = malloc(iterend);
- for (struct fragment *iter = inc->first; iter; iter = iter->next) {
- assert(iter->offset + iter->len <= iterend);
- memcpy(buf + iter->offset, iter->buf, iter->len);
- }
- ipv4_dispatch(buf, iterend, inc->h);
- free(buf);
- fragmented_free(inc);
- }
- }
-}
-
-static void fragmented_free(struct fragmented *inc) {
- if (inc->next) {
- inc->next->prev = inc->prev;
- *inc->next->prev = inc->next;
- } else {
- *inc->prev = NULL;
- }
-
- for (struct fragment *next, *iter = inc->first; iter; iter = next) {
- next = iter->next;
- free(iter);
- }
- free((void*)inc->h.header);
- free(inc);
-}
-
-
-static void ipv4_dispatch(const uint8_t *buf, size_t len, struct ipv4 ip) {
- switch (ip.proto) {
- case 0x01: icmp_parse(buf, len, ip); break;
- case 0x06: tcp_parse(buf, len, ip); break;
- case 0x11: udp_parse(buf, len, ip); break;
- }
-}
-
-void ipv4_parse(const uint8_t *buf, size_t len, struct ethernet ether) {
- uint8_t version, headerlen;
- uint16_t totallen;
-
- version = buf[Version] >> 4;
- if (version != 4) return;
- headerlen = (buf[HdrLen] & 0xf) * 4;
- totallen = nget16(buf + TotalLen);
- if (totallen < headerlen) return;
-
- /* ignores checksum. TODO? */
-
- struct ipv4 ip = (struct ipv4){
- .e = ether,
- .src = nget32(buf + SrcIP),
- .dst = nget32(buf + DstIP),
- .id = nget16(buf + Id),
- .fraginfo = nget16(buf + FragInfo),
- .proto = buf[Proto],
- .header = buf,
- .hlen = headerlen,
- };
-
- if (ip.fraginfo & ~(EvilBit | DontFrag)) {
- fragmented_tryinsert(buf + headerlen, totallen - headerlen, ip);
- } else {
- if (totallen > len) return;
- ipv4_dispatch(buf + headerlen, totallen - headerlen, ip);
- }
-}
-
-static uint16_t next_id = 0;
-void ipv4_send(const void *payload, size_t len, struct ipv4 ip) {
- const size_t mtu = 1500;
- const size_t hdrlen = 20;
-
- ip.e.type = ET_IPv4;
- if (!ip.src) ip.src = state.ip;
- if (!ip.e.dst && ip.dst == 0xFFFFFFFF)
- ip.e.dst = &MAC_BROADCAST;
-
- uint16_t id = next_id++;
- for (size_t off = 0, fraglen = mtu - hdrlen; off < len; off += fraglen) {
- if (fraglen > len - off)
- fraglen = len - off;
- bool last = off + fraglen >= len;
- uint8_t *pkt = ether_start(hdrlen + fraglen, ip.e);
- pkt[Version] = 0x40;
- pkt[HdrLen] |= hdrlen / 4;
- nput16(pkt + TotalLen, hdrlen + fraglen);
- nput16(pkt + Id, id);
- nput16(pkt + FragInfo, (off >> 3) | (last ? 0 : MoreFrags));
- pkt[TTL] = 0xFF;
- pkt[Proto] = ip.proto;
- nput32(pkt + SrcIP, ip.src);
- nput32(pkt + DstIP, ip.dst);
- nput16(pkt + Checksum, ip_checksum(pkt, hdrlen));
- memcpy(pkt + hdrlen, payload + off, fraglen);
- ether_finish(pkt);
- }
-}
diff --git a/src/user/app/netstack/netstack.c b/src/user/app/netstack/netstack.c
deleted file mode 100644
index 2636429..0000000
--- a/src/user/app/netstack/netstack.c
+++ /dev/null
@@ -1,53 +0,0 @@
-#include "proto.h"
-#include "util.h"
-#include <camellia.h>
-#include <camellia/syscalls.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <thread.h>
-
-struct net_state state = {
- // TODO dynamically get mac
- .mac = {0x52, 0x54, 0x00, 0xCA, 0x77, 0x1A},
-};
-
-void network_thread(void *arg) { (void)arg;
- const size_t buflen = 4096;
- char *buf = malloc(buflen);
- for (;;) {
- long ret = _sys_read(state.raw_h, buf, buflen, -1);
- if (ret < 0) break;
- ether_parse((void*)buf, ret);
- }
- free(buf);
-}
-
-void fs_thread(void *arg);
-
-int main(int argc, char **argv) {
- if (argc < 4) {
- eprintf("usage: netstack iface ip gateway");
- return 1;
- }
- state.raw_h = camellia_open(argv[1], OPEN_RW);
- if (state.raw_h < 0) {
- eprintf("couldn't open %s", argv[1]);
- return 1;
- }
- if (ip_parse(argv[2], &state.ip) < 0) {
- eprintf("invalid ip");
- return -1;
- }
- if (ip_parse(argv[3], &state.gateway) < 0) {
- eprintf("invalid gateway");
- return -1;
- }
- setproctitle(argv[2]);
- arp_request(state.gateway);
- thread_create(0, network_thread, NULL);
- thread_create(0, fs_thread, NULL);
- _sys_await();
- return 0;
-}
diff --git a/src/user/app/netstack/proto.h b/src/user/app/netstack/proto.h
deleted file mode 100644
index 8ea11ac..0000000
--- a/src/user/app/netstack/proto.h
+++ /dev/null
@@ -1,107 +0,0 @@
-#pragma once
-#include <camellia/types.h>
-#include <stdbool.h>
-#include <stdint.h>
-
-typedef uint8_t mac_t[6];
-static const mac_t MAC_BROADCAST = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
-
-extern struct net_state {
- mac_t mac;
- uint32_t ip, gateway;
-
- hid_t raw_h;
-} state;
-
-enum { /* ethertype */
- ET_IPv4 = 0x800,
- ET_ARP = 0x806,
-};
-
-struct ethernet {
- const mac_t *src, *dst;
- uint16_t type;
-};
-
-struct ipv4 {
- struct ethernet e;
- uint32_t src, dst;
- uint16_t id, fraginfo;
- uint8_t proto;
- const uint8_t *header; size_t hlen;
-};
-
-struct tcp {
- struct ipv4 ip;
- uint16_t src, dst;
-};
-
-struct udp {
- struct ipv4 ip;
- uint16_t src, dst;
-};
-
-struct icmp {
- struct ipv4 ip;
- uint8_t type, code;
-};
-
-
-/* NOT THREADSAFE, YET USED FROM CONCURRENT THREADS
- * will break if i implement a scheduler*/
-struct ethq {
- struct ethq *next;
- hid_t h;
-};
-extern struct ethq *ether_queue;
-
-void arp_parse(const uint8_t *buf, size_t len);
-void arp_request(uint32_t ip);
-/* 0 on success, -1 on failure */
-int arpcache_get(uint32_t ip, mac_t *mac);
-void arp_fsread(hid_t h, long offset);
-long arp_fswrite(const char *buf, long len, 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);
-
-void ipv4_parse(const uint8_t *buf, size_t len, struct ethernet ether);
-void ipv4_send(const void *payload, size_t len, struct ipv4 ip);
-
-void ether_parse(const uint8_t *buf, size_t len);
-uint8_t *ether_start(size_t len, struct ethernet ether);
-void ether_finish(uint8_t *pkt);
-
-struct udp_conn;
-void udp_parse(const uint8_t *buf, size_t len, struct ipv4 ip);
-/* calls callback once, after a client connects. */
-void udp_listen(
- uint16_t port,
- void (*on_conn)(struct udp_conn *, void *carg),
- void (*on_recv)(const void *, size_t, void *carg),
- void *carg);
-struct udp_conn *udpc_new(
- struct udp u,
- void (*on_recv)(const void *, size_t, void *carg),
- void *carg);
-// TODO udp_onclosed
-void udpc_send(struct udp_conn *, const void *buf, size_t len);
-/* frees */
-void udpc_close(struct udp_conn *);
-
-struct tcp_conn;
-void tcp_parse(const uint8_t *buf, size_t len, struct ipv4 ip);
-void tcp_listen(
- uint16_t port,
- void (*on_conn)(struct tcp_conn *, void *carg),
- void (*on_recv)(void *carg),
- void (*on_close)(void *carg),
- void *carg);
-struct tcp_conn *tcpc_new(
- struct tcp t,
- void (*on_recv)(void *carg),
- void (*on_close)(void *carg),
- void *carg);
-size_t tcpc_tryread(struct tcp_conn *, void *buf, size_t len);
-void tcpc_send(struct tcp_conn *, const void *buf, size_t len);
-void tcpc_close(struct tcp_conn *);
diff --git a/src/user/app/netstack/tcp.c b/src/user/app/netstack/tcp.c
deleted file mode 100644
index d1adeab..0000000
--- a/src/user/app/netstack/tcp.c
+++ /dev/null
@@ -1,268 +0,0 @@
-/* Welcome to spaghetti land.
- * This is anything but production quality. It's throwaway code, meant
- * only to see how networking could fit into the architecture of the
- * system. */
-#include "proto.h"
-#include "util.h"
-#include <assert.h>
-#include <shared/ring.h>
-
-enum {
- SrcPort = 0,
- DstPort = 2,
- Seq = 4,
- AckNum = 8, /* last processed seq + 1 */
- Flags = 12,
- FlagSize = 0xF000, /* size of header / 4 bytes */
- /* 3 bits: 0, still unused
- * 3 bits: modern stuff not in the original RFC */
- FlagURG = 0x0020, /* urgent */
- FlagACK = 0x0010,
- FlagPSH = 0x0008, /* force buffer flush */
- FlagRST = 0x0004, /* reset connection */
- FlagSYN = 0x0002, /* first packet; sync sequence numbers */
- FlagFIN = 0x0001, /* last packet */
- FlagAll = 0x003F,
- WinSize = 14, /* amount of data we're willing to receive */
- Checksum = 16,
- Urgent = 18,
- MinHdr = 20,
-};
-
-enum tcp_state {
- LISTEN,
- SYN_SENT,
- SYN_RCVD,
- ESTABILISHED,
- LAST_ACK,
- CLOSED,
-};
-
-struct tcp_conn {
- uint32_t lip, rip;
- mac_t rmac;
- uint16_t lport, rport;
- struct tcp_conn *next, **link;
-
- enum tcp_state state;
- uint32_t lack, rack;
- uint32_t lseq;
- bool uclosed; /* did the user close? */
-
- void (*on_conn)(struct tcp_conn *, void *carg);
- void (*on_recv)(void *carg);
- void (*on_close)(void *carg);
- void *carg;
-
- ring_t rx;
-};
-static struct tcp_conn *conns;
-static void conns_append(struct tcp_conn *c) {
- c->next = conns;
- if (c->next)
- c->next->link = &c->next;
- c->link = &conns;
- *c->link = c;
-}
-static void tcpc_sendraw(struct tcp_conn *c, uint16_t flags, const void *buf, size_t len) {
- uint8_t *pkt = malloc(MinHdr + len);
- memset(pkt, 0, MinHdr);
-
- nput16(pkt + SrcPort, c->lport);
- nput16(pkt + DstPort, c->rport);
- nput32(pkt + Seq, c->lseq);
- c->lseq += len;
- nput32(pkt + AckNum, c->lack);
- flags |= (MinHdr / 4) << 12;
- nput16(pkt + Flags, flags);
- nput16(pkt + WinSize, ring_avail(&c->rx));
- memcpy(pkt + MinHdr, buf, len);
- nput16(pkt + Checksum, ip_checksumphdr(pkt, MinHdr + len, c->lip, c->rip, 6));
-
- ipv4_send(pkt, MinHdr + len, (struct ipv4){
- .proto = 6,
- .src = c->lip,
- .dst = c->rip,
- .e.dst = &c->rmac,
- });
- free(pkt);
-}
-void tcp_listen(
- uint16_t port,
- void (*on_conn)(struct tcp_conn *, void *carg),
- void (*on_recv)(void *carg),
- void (*on_close)(void *carg),
- void *carg)
-{
- struct tcp_conn *c = malloc(sizeof *c);
- memset(c, 0, sizeof *c);
- c->lport = port;
- c->lip = state.ip;
- c->state = LISTEN;
- c->on_conn = on_conn;
- c->on_recv = on_recv;
- c->on_close = on_close;
- c->carg = carg;
- // TODO setting the ring size super low loses every nth byte. probably a bug with ring_t itself!
- c->rx = (ring_t){malloc(4096), 4096, 0, 0};
- conns_append(c);
-}
-struct tcp_conn *tcpc_new(
- struct tcp t,
- void (*on_recv)(void *carg),
- void (*on_close)(void *carg),
- void *carg)
-{
- struct tcp_conn *c = malloc(sizeof *c);
- memset(c, 0, sizeof *c);
- c->lip = t.ip.src ? t.ip.src : state.ip;
- c->rip = t.ip.dst;
- c->lport = t.src ? t.src : 50002; // TODO randomize source ports
- c->rport = t.dst;
- if (arpcache_get(c->rip, &c->rmac) < 0) {
- // TODO wait for ARP reply
- arp_request(c->rip);
- if (arpcache_get(state.gateway, &c->rmac) < 0) {
- eprintf("neither target nor gateway not in ARP cache, dropping");
- free(c);
- return NULL;
- }
- }
-
- c->state = SYN_SENT;
- c->on_recv = on_recv;
- c->on_close = on_close;
- c->carg = carg;
- c->rx = (ring_t){malloc(4096), 4096, 0, 0};
- conns_append(c);
-
- tcpc_sendraw(c, FlagSYN, NULL, 0);
- c->lseq++;
- return c;
-}
-size_t tcpc_tryread(struct tcp_conn *c, void *buf, size_t len) {
- if (!buf) return ring_used(&c->rx);
- return ring_get(&c->rx, buf, len);
-}
-void tcpc_send(struct tcp_conn *c, const void *buf, size_t len) {
- tcpc_sendraw(c, FlagACK | FlagPSH, buf, len);
-}
-static void tcpc_tryfree(struct tcp_conn *c) {
- if (c->state == CLOSED && c->uclosed) {
- if (c->next) c->next->link = c->link;
- *c->link = c->next;
- free(c->rx.buf);
- free(c);
- }
-}
-void tcpc_close(struct tcp_conn *c) {
- /* ONLY FOR USE BY THE USER, drops their reference */
- assert(!c->uclosed);
- c->uclosed = true;
- if (c->state != CLOSED && c->state != LAST_ACK && c->state != LISTEN) {
- tcpc_sendraw(c, FlagFIN | FlagACK, NULL, 0);
- c->state = LAST_ACK;
- c->on_conn = NULL;
- c->on_close = NULL;
- }
- tcpc_tryfree(c);
-}
-
-void tcp_parse(const uint8_t *buf, size_t len, struct ipv4 ip) {
- if (len < 20) return;
- uint16_t srcport = nget16(buf + SrcPort);
- uint16_t dstport = nget16(buf + DstPort);
- uint32_t seq = nget32(buf + Seq);
- uint32_t acknum = nget32(buf + AckNum);
- uint16_t flags = nget16(buf + Flags);
- // uint16_t winsize = nget16(buf + WinSize);
- // uint16_t chksum = nget16(buf + Checksum);
- uint16_t hdrlen = ((flags & FlagSize) >> 12) * 4;
- if (hdrlen > len) return;
- uint16_t payloadlen = len - hdrlen;
-
- for (struct tcp_conn *iter = conns; iter; iter = iter->next) {
- if (iter->state == CLOSED) continue;
- if (iter->lport != dstport) continue;
-
- if (iter->state == LISTEN && (flags & FlagAll) == FlagSYN) {
- iter->state = SYN_RCVD;
- iter->rip = ip.src;
- iter->rport = srcport;
- iter->lack = seq + 1;
- memcpy(&iter->rmac, ip.e.src, sizeof(mac_t));
- tcpc_sendraw(iter, FlagSYN | FlagACK, NULL, 0);
- iter->lseq++;
- if (iter->on_conn) iter->on_conn(iter, iter->carg);
- return;
- }
-
- if (iter->rip == ip.src && iter->rport == srcport) {
- // TODO doesn't handle seq/ack overflows
- if (iter->state == SYN_SENT) {
- if (flags & FlagSYN) {
- iter->state = ESTABILISHED;
- iter->lack = seq + 1;
- tcpc_sendraw(iter, FlagACK, NULL, 0);
- return;
- } else {
- // TODO resend syn?
- return;
- }
- }
- if (flags & FlagACK) {
- if (iter->rack < acknum)
- iter->rack = acknum;
- if (iter->state == LAST_ACK) {
- // TODO check if ack has correct number
- iter->state = CLOSED;
- tcpc_tryfree(iter);
- // TODO free (also after a timeout)
- return;
- }
- }
- if (iter->lack != seq && iter->lack - 1 != seq) {
- eprintf("remote seq jumped by %d", seq - iter->lack);
- tcpc_sendraw(iter, FlagACK, NULL, 0);
- return;
- }
- // TODO check if overflows window size
- if (payloadlen) {
- iter->lack = seq + payloadlen;
- ring_put(&iter->rx, buf + hdrlen, payloadlen);
- if (iter->on_recv) iter->on_recv(iter->carg);
- tcpc_sendraw(iter, FlagACK, NULL, 0);
- }
- if (flags & FlagFIN) {
- // TODO should resend the packet until an ACK is received
- // TODO duplicated in tcpc_close
- tcpc_sendraw(iter, FlagFIN | FlagACK, NULL, 0);
- iter->state = LAST_ACK;
- if (iter->on_close) iter->on_close(iter->carg);
- return;
- }
- return;
- }
- }
-
- if ((flags & FlagRST) == 0) {
- uint8_t *pkt = malloc(MinHdr);
- memset(pkt, 0, MinHdr);
- nput16(pkt + SrcPort, dstport);
- nput16(pkt + DstPort, srcport);
- nput32(pkt + Seq, acknum);
- nput32(pkt + AckNum, seq + 1);
- uint16_t pktflags = FlagRST | FlagACK;
- pktflags |= (MinHdr / 4) << 12;
- nput16(pkt + Flags, pktflags);
- nput16(pkt + Checksum, ip_checksumphdr(pkt, MinHdr, ip.src, ip.dst, 6));
-
- ipv4_send(pkt, MinHdr, (struct ipv4){
- .proto = 6,
- .src = ip.dst,
- .dst = ip.src,
- .e.dst = ip.e.src,
- });
- free(pkt);
- }
-}
diff --git a/src/user/app/netstack/udp.c b/src/user/app/netstack/udp.c
deleted file mode 100644
index 3d560ae..0000000
--- a/src/user/app/netstack/udp.c
+++ /dev/null
@@ -1,124 +0,0 @@
-#include "proto.h"
-#include "util.h"
-
-enum {
- SrcPort = 0,
- DstPort = 2,
- Length = 4,
- Checksum = 6,
- Payload = 8,
-};
-
-
-struct udp_conn {
- uint32_t lip, rip;
- uint16_t lport, rport;
- mac_t rmac;
- void (*on_conn)(struct udp_conn *, void *); /* if non-NULL - listening, if NULL - estabilished */
- void (*on_recv)(const void *, size_t, void *);
- void *carg;
- struct udp_conn *next, **link;
-};
-static struct udp_conn *conns;
-static void conns_append(struct udp_conn *c) {
- c->next = conns;
- if (c->next)
- c->next->link = &c->next;
- c->link = &conns;
- *c->link = c;
-}
-void udp_listen(
- uint16_t port,
- void (*on_conn)(struct udp_conn *, void *carg),
- void (*on_recv)(const void *, size_t, void *carg),
- void *carg)
-{
- if (!on_conn) return;
- struct udp_conn *c = malloc(sizeof *c);
- c->lport = port;
- c->lip = state.ip;
- c->on_conn = on_conn;
- c->on_recv = on_recv;
- c->carg = carg;
- conns_append(c);
-}
-struct udp_conn *udpc_new(
- struct udp u,
- void (*on_recv)(const void *, size_t, void *carg),
- void *carg)
-{
- struct udp_conn *c = malloc(sizeof *c);
- memset(c, 0, sizeof *c);
- c->lip = u.ip.src;
- c->rip = u.ip.dst;
- c->lport = u.src ? u.src : 50000; // TODO randomize source ports
- c->rport = u.dst;
- if (arpcache_get(c->rip, &c->rmac) < 0) {
- // TODO make arp request, wait for reply
- eprintf("not in ARP cache, unimplemented");
- free(c);
- return NULL;
- }
- c->on_recv = on_recv;
- c->carg = carg;
- conns_append(c);
- return c;
-}
-void udpc_send(struct udp_conn *c, const void *buf, size_t len) {
- uint8_t *pkt = malloc(Payload + len);
- nput16(pkt + SrcPort, c->lport);
- nput16(pkt + DstPort, c->rport);
- nput16(pkt + Length, Payload + len);
- nput16(pkt + Checksum, 0);
- memcpy(pkt + Payload, buf, len);
- ipv4_send(pkt, Payload + len, (struct ipv4){
- .proto = 0x11,
- .src = c->lip,
- .dst = c->rip,
- .e.dst = &c->rmac,
- });
- free(pkt);
-}
-void udpc_close(struct udp_conn *c) {
- if (c->next) c->next->link = c->link;
- *(c->link) = c->next;
- free(c);
-}
-
-
-void udp_parse(const uint8_t *buf, size_t len, struct ipv4 ip) {
- uint16_t srcport = nget16(buf + SrcPort);
- uint16_t dstport = nget16(buf + DstPort);
- bool active = false;
-
- for (struct udp_conn *iter = conns; iter; iter = iter->next) {
- if (iter->on_conn && dstport == iter->lport) {
- iter->on_conn(iter, iter->carg);
- iter->on_conn = NULL;
- iter->rport = srcport;
- memcpy(&iter->rmac, ip.e.src, sizeof(mac_t));
- iter->rip = ip.src;
- }
- if (iter->rip == ip.src &&
- iter->rport == srcport &&
- iter->lport == dstport &&
- iter->on_recv)
- {
- active = true;
- iter->on_recv(buf + Payload, len - Payload, iter->carg);
- }
- }
-
- if (!active) {
- uint8_t *pkt = malloc(4 + ip.hlen + 8);
- nput32(pkt, 0);
- memcpy(pkt + 4, ip.header, ip.hlen + 8);
- icmp_send(pkt, 4 + ip.hlen + 8, (struct icmp){
- .type = 3, /* destination unreachable */
- .code = 3, /* port unreachable */
- .ip.dst = ip.src,
- .ip.e.dst = ip.e.src,
- });
- free(pkt);
- }
-}
diff --git a/src/user/app/netstack/util.c b/src/user/app/netstack/util.c
deleted file mode 100644
index 68092aa..0000000
--- a/src/user/app/netstack/util.c
+++ /dev/null
@@ -1,60 +0,0 @@
-#include "util.h"
-
-/* https://www.w3.org/TR/PNG/#D-CRCAppendix */
-static uint32_t crc_table[256];
-uint32_t crc32(const uint8_t *buf, size_t len) {
- if (!crc_table[1]) {
- for (int i = 0; i < 256; i++) {
- uint32_t c = i;
- for (int j = 0; j < 8; j++)
- c = ((c&1) ? 0xedb88320 : 0) ^ (c >> 1);
- crc_table[i] = c;
- }
- }
-
- uint32_t c = 0xFFFFFFFF;
- for (size_t i = 0; i < len; i++)
- c = crc_table[(c ^ buf[i]) & 0xff] ^ (c >> 8);
- return ~c;
-}
-
-uint16_t ip_checksum(const uint8_t *buf, size_t len) {
- uint32_t c = 0;
- while (len >= 2) {
- c += nget16(buf);
- buf += 2; len -= 2;
- }
- if (len) c += (*buf) << 8;
- while (c > 0xFFFF) c = (c & 0xFFFF) + (c >> 16);
- return ~c;
-}
-
-uint16_t ip_checksumphdr(
- const uint8_t *buf, size_t len,
- uint32_t ip1, uint32_t ip2,
- uint16_t proto)
-{
- uint32_t c = (uint16_t)~ip_checksum(buf, len);
- c += (ip1 & 0xFFFF) + (ip1 >> 16);
- c += (ip2 & 0xFFFF) + (ip2 >> 16);
- c += proto + len;
- while (c > 0xFFFF) c = (c & 0xFFFF) + (c >> 16);
- return ~c;
-}
-
-int ip_parse(const char *s, uint32_t *dest) {
- if (!s) return -1;
-
- uint32_t ip = strtol(s, (char**)&s, 0);
- int parts = 1;
- for (; parts < 4; parts++) {
- if (!*s) break;
- if (*s++ != '.') return -1;
- ip <<= 8;
- ip += strtol(s, (char**)&s, 0);
- }
- if (parts > 1)
- ip = ((ip & 0xFFFFFF00) << 8 * (4 - parts)) | (ip & 0xFF);
- *dest = ip;
- return 0;
-}
diff --git a/src/user/app/netstack/util.h b/src/user/app/netstack/util.h
deleted file mode 100644
index 0b29560..0000000
--- a/src/user/app/netstack/util.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#pragma once
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#define eprintf(fmt, ...) fprintf(stderr, "netstack: "fmt"\n" __VA_OPT__(,) __VA_ARGS__)
-
-uint32_t crc32(const uint8_t *buf, size_t len);
-uint16_t ip_checksum(const uint8_t *buf, size_t len);
-uint16_t ip_checksumphdr(
- const uint8_t *buf, size_t len,
- uint32_t ip1, uint32_t ip2,
- uint16_t proto);
-/* 0 on success, negative failure */
-int ip_parse(const char *s, uint32_t *ip);
-
-static inline void nput16(void *vbuf, uint16_t n) {
- uint8_t *b = vbuf;
- b[0] = n >> 8;
- b[1] = n >> 0;
-}
-
-static inline void nput32(void *vbuf, uint32_t n) {
- uint8_t *b = vbuf;
- b[0] = n >> 24;
- b[1] = n >> 16;
- b[2] = n >> 8;
- b[3] = n >> 0;
-}
-
-static inline uint16_t nget16(const void *vbuf) {
- const uint8_t *b = vbuf;
- return (b[0] << 8)
- | (b[1] << 0);
-}
-
-static inline uint32_t nget32(const void *vbuf) {
- const uint8_t *b = vbuf;
- return (b[0] << 24)
- | (b[1] << 16)
- | (b[2] << 8)
- | (b[3] << 0);
-}