diff options
author | dzwdz | 2022-08-22 17:48:29 +0200 |
---|---|---|
committer | dzwdz | 2022-08-22 17:48:29 +0200 |
commit | 55900142023f7a27d467c7ce6a61d2e5ecead4e3 (patch) | |
tree | 98f3bb6af3b174d5ebc599838c237c676e20431c | |
parent | 150303b2b88fff33dba96d6fabaf517bec3fb9ec (diff) |
user/netstack: outgoing UDP connections
-rw-r--r-- | src/user/app/netstack/arp.c | 10 | ||||
-rw-r--r-- | src/user/app/netstack/fs.c | 35 | ||||
-rw-r--r-- | src/user/app/netstack/proto.h | 14 | ||||
-rw-r--r-- | src/user/app/netstack/udp.c | 45 |
4 files changed, 87 insertions, 17 deletions
diff --git a/src/user/app/netstack/arp.c b/src/user/app/netstack/arp.c index b43b7e8..9e292b3 100644 --- a/src/user/app/netstack/arp.c +++ b/src/user/app/netstack/arp.c @@ -73,6 +73,16 @@ static void arpcache_put(uint32_t ip, mac_t mac) { 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(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; diff --git a/src/user/app/netstack/fs.c b/src/user/app/netstack/fs.c index dc6db04..4d1e38c 100644 --- a/src/user/app/netstack/fs.c +++ b/src/user/app/netstack/fs.c @@ -42,8 +42,6 @@ struct handle { static void udp_listen_callback(struct udp_conn *c, void *arg) { struct handle *h = arg; h->udp.c = c; - h->udp.rx = NULL; - h->udp.rxlast = NULL; _syscall_fs_respond(h->reqh, h, 0, 0); h->reqh = -1; } @@ -55,7 +53,6 @@ static void udp_recv_callback(const void *buf, size_t len, void *arg) { h->reqh = -1; return; } - // TODO don't malloc on the network thread, dumbass struct strqueue *sq = malloc(sizeof(*sq) + len); sq->next = NULL; sq->len = len; @@ -99,10 +96,10 @@ static void fs_open(handle_t reqh, char *path) { } char *save; - const char *srcip, *verb, *proto, *port_s; + const char *srcip_s, *dstip_s, *verb, *proto, *port_s; - srcip = strtok_r(path, "/", &save); - if (strcmp(srcip, "0.0.0.0") != 0) + srcip_s = strtok_r(path, "/", &save); + if (strcmp(srcip_s, "0.0.0.0") != 0) respond(NULL, -1); verb = strtok_r(NULL, "/", &save); @@ -113,6 +110,7 @@ static void fs_open(handle_t reqh, char *path) { 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 = NULL; h->reqh = reqh; @@ -120,6 +118,31 @@ static void fs_open(handle_t reqh, char *path) { return; } } + } else if (strcmp(verb, "connect") == 0) { + dstip_s = strtok_r(NULL, "/", &save); + // TODO proper ip parsing + // 0xc0a80001 == 192.168.0.1 + uint32_t dstip = strtol(dstip_s, NULL, 0); + proto = strtok_r(NULL, "/", &save); + 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 diff --git a/src/user/app/netstack/proto.h b/src/user/app/netstack/proto.h index 864f1c1..68dccad 100644 --- a/src/user/app/netstack/proto.h +++ b/src/user/app/netstack/proto.h @@ -31,6 +31,11 @@ struct ipv4 { const uint8_t *header; size_t hlen; }; +struct udp { + struct ipv4 ip; + uint16_t src, dst; +}; + struct icmp { struct ipv4 ip; uint8_t type, code; @@ -46,6 +51,8 @@ struct ethq { extern struct ethq *ether_queue; void arp_parse(const uint8_t *buf, size_t len); +/* 0 on success, -1 on failure */ +int arpcache_get(uint32_t ip, mac_t *mac); void arp_fsread(handle_t h, long offset); void icmp_parse(const uint8_t *buf, size_t len, struct ipv4 ip); @@ -61,10 +68,15 @@ 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 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 */ diff --git a/src/user/app/netstack/udp.c b/src/user/app/netstack/udp.c index d53137d..46d09de 100644 --- a/src/user/app/netstack/udp.c +++ b/src/user/app/netstack/udp.c @@ -20,7 +20,14 @@ struct udp_conn { struct udp_conn *next, **prev; }; struct udp_conn *conns; -void udp_listen(uint16_t port, +static void conns_append(struct udp_conn *c) { + c->next = conns; + if (c->next) *(c->next->prev) = c; + c->prev = &conns; + *c->prev = 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) @@ -32,16 +39,29 @@ void udp_listen(uint16_t port, c->on_conn = on_conn; c->on_recv = on_recv; c->carg = carg; - - c->next = conns; - if (c->next) *(c->next->prev) = c; - c->prev = &conns; - *c->prev = c; + conns_append(c); } -void udpc_close(struct udp_conn *c) { - if (c->next) c->next->prev = c->prev; - *(c->prev) = c->next; - free(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); @@ -58,6 +78,11 @@ void udpc_send(struct udp_conn *c, const void *buf, size_t len) { }); free(pkt); } +void udpc_close(struct udp_conn *c) { + if (c->next) c->next->prev = c->prev; + *(c->prev) = c->next; + free(c); +} void udp_parse(const uint8_t *buf, size_t len, struct ipv4 ip) { |