From 4be1fd62131f7e186e6f92f1bb5a356dc1ac1951 Mon Sep 17 00:00:00 2001
From: dzwdz
Date: Mon, 25 Dec 2023 20:12:44 +0100
Subject: user/libc: reorganize net stuff, basic hosts-only gethostbyname()

/usr/share/hosts because i don't have /etc/ yet and i don't feel like creating it.
---
 src/cmd/netstack/util.c      |  1 +
 src/libc/arpainet.c          | 20 ---------
 src/libc/include/arpa/inet.h |  3 ++
 src/libc/net/arpainet.c      | 38 ++++++++++++++++++
 src/libc/net/gethostbyname.c | 51 +++++++++++++++++++++++
 src/libc/net/socket.c        | 91 +++++++++++++++++++++++++++++++++++++++++
 src/libc/socket.c            | 96 --------------------------------------------
 sysroot/usr/share/hosts      |  8 ++++
 8 files changed, 192 insertions(+), 116 deletions(-)
 delete mode 100644 src/libc/arpainet.c
 create mode 100644 src/libc/net/arpainet.c
 create mode 100644 src/libc/net/gethostbyname.c
 create mode 100644 src/libc/net/socket.c
 delete mode 100644 src/libc/socket.c
 create mode 100644 sysroot/usr/share/hosts

diff --git a/src/cmd/netstack/util.c b/src/cmd/netstack/util.c
index 68092aa..093c5ac 100644
--- a/src/cmd/netstack/util.c
+++ b/src/cmd/netstack/util.c
@@ -43,6 +43,7 @@ uint16_t ip_checksumphdr(
 }
 
 int ip_parse(const char *s, uint32_t *dest) {
+	// TODO use inet_aton
 	if (!s) return -1;
 
 	uint32_t ip = strtol(s, (char**)&s, 0);
diff --git a/src/libc/arpainet.c b/src/libc/arpainet.c
deleted file mode 100644
index 125a855..0000000
--- a/src/libc/arpainet.c
+++ /dev/null
@@ -1,20 +0,0 @@
-#include <arpa/inet.h>
-
-uint32_t htonl(uint32_t n) {
-	return ((n & 0xFF000000) >> 24)
-	     | ((n & 0x00FF0000) >>  8)
-	     | ((n & 0x0000FF00) <<  8)
-	     | ((n & 0x000000FF) << 24);
-}
-
-uint16_t htons(uint16_t n) {
-	return (n >> 8) | (n << 8);
-}
-
-uint32_t ntohl(uint32_t n) {
-	return htonl(n);
-}
-
-uint16_t ntohs(uint16_t n) {
-	return htons(n);
-}
diff --git a/src/libc/include/arpa/inet.h b/src/libc/include/arpa/inet.h
index d372467..1e4f97e 100644
--- a/src/libc/include/arpa/inet.h
+++ b/src/libc/include/arpa/inet.h
@@ -1,4 +1,5 @@
 #pragma once
+#include <netinet/in.h>
 #include <stdint.h>
 
 uint32_t htonl(uint32_t n);
@@ -6,3 +7,5 @@ uint16_t htons(uint16_t n);
 
 uint32_t ntohl(uint32_t n);
 uint16_t ntohs(uint16_t n);
+
+int inet_aton(const char *s, struct in_addr *dest);
diff --git a/src/libc/net/arpainet.c b/src/libc/net/arpainet.c
new file mode 100644
index 0000000..62efb62
--- /dev/null
+++ b/src/libc/net/arpainet.c
@@ -0,0 +1,38 @@
+#include <arpa/inet.h>
+#include <stdlib.h>
+
+uint32_t htonl(uint32_t n) {
+	return ((n & 0xFF000000) >> 24)
+	     | ((n & 0x00FF0000) >>  8)
+	     | ((n & 0x0000FF00) <<  8)
+	     | ((n & 0x000000FF) << 24);
+}
+
+uint16_t htons(uint16_t n) {
+	return (n >> 8) | (n << 8);
+}
+
+uint32_t ntohl(uint32_t n) {
+	return htonl(n);
+}
+
+uint16_t ntohs(uint16_t n) {
+	return htons(n);
+}
+
+int inet_aton(const char *s, struct in_addr *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 0;
+		ip <<= 8;
+		ip += strtol(s, (char**)&s, 0);
+	}
+	if (parts > 1)
+		ip = ((ip & 0xFFFFFF00) << 8 * (4 - parts)) | (ip & 0xFF);
+	dest->s_addr = htonl(ip);
+	return 1;
+}
diff --git a/src/libc/net/gethostbyname.c b/src/libc/net/gethostbyname.c
new file mode 100644
index 0000000..f2b59c1
--- /dev/null
+++ b/src/libc/net/gethostbyname.c
@@ -0,0 +1,51 @@
+#include <arpa/inet.h>
+#include <ctype.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct hostent *gethostbyname(const char *name) {
+	// TODO ipv4 addresses should just get copied
+	static struct hostent he;
+	static struct in_addr addr;
+	static void *addrs[2] = {NULL, NULL};
+	bool found = false;
+	char buf[256];
+	FILE *fp;
+
+	if (he.h_name) {
+		free(he.h_name);
+		he.h_name = NULL;
+	}
+
+	if ((fp = fopen("/usr/share/hosts", "r")) == NULL) {
+		return NULL;
+	}
+	while (!found && fgets(buf, sizeof buf, fp)) {
+		char *s;
+		if (!isdigit(buf[0])) continue;
+		s = strtok(buf, " \t\n");
+		if (!inet_aton(s, &addr)) continue;
+		while ((s = strtok(NULL, " \t\n"))) {
+			if (strcmp(s, name) == 0) {
+				found = true;
+				break;
+			}
+		}
+	}
+	fclose(fp);
+	if (!found) {
+		return NULL;
+	}
+
+	he.h_name = strdup(name);
+	he.h_aliases = NULL;
+	he.h_addrtype = AF_INET;
+	he.h_length = 4;
+	he.h_addr_list = (void*)&addrs;
+	addrs[0] = &addr.s_addr;
+	return &he;
+}
diff --git a/src/libc/net/socket.c b/src/libc/net/socket.c
new file mode 100644
index 0000000..9eacbe5
--- /dev/null
+++ b/src/libc/net/socket.c
@@ -0,0 +1,91 @@
+#include <arpa/inet.h>
+#include <camellia.h>
+#include <camellia/syscalls.h>
+#include <errno.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <sys/socket.h>
+
+int socket(int domain, int type, int protocol) {
+	if (domain != AF_INET || type != SOCK_STREAM || protocol != IPPROTO_TCP) {
+		return errno = ENOSYS, -1;
+	}
+	int h = _sys_getnull(0);
+	if (h < 0) {
+		return errno = -h, -1;
+	} else {
+		return h;
+	}
+}
+
+int bind(int, const struct sockaddr *, socklen_t) {
+	return errno = ENOSYS, -1;
+}
+
+int accept(int, struct sockaddr *, socklen_t *) {
+	return errno = ENOSYS, -1;
+}
+
+int listen(int, int) {
+	return errno = ENOSYS, -1;
+}
+
+int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
+	char buf[256];
+	struct sockaddr_in *addr4 = (void*)addr;
+	uint32_t ip;
+	uint16_t port;
+	int newfd;
+
+	if (addr->sa_family != AF_INET) {
+		return errno = ENOSYS, -1;
+	}
+
+	if (addrlen < (ssize_t)sizeof(*addr4)) {
+		return errno = EINVAL, -1;
+	}
+
+	ip   = ntohl(addr4->sin_addr.s_addr);
+	port = ntohs(addr4->sin_port);
+	if (snprintf(buf, 256, "/net/connect/0/%ld/tcp/%d", ip, port) >= 256) {
+		return errno = EGENERIC, -1;
+	}
+	newfd = camellia_open(buf, OPEN_READ | OPEN_WRITE);
+	if (newfd < 0) {
+		return -1;
+	}
+	dup2(newfd, sockfd);
+	close(newfd);
+	return 0;
+}
+
+ssize_t send(int sockfd, const void *buf, size_t len, int flags) {
+	if (flags != 0) {
+		return errno = ENOSYS, -1;
+	}
+	return write(sockfd, buf, len);
+}
+
+ssize_t recv(int sockfd, void *buf, size_t len, int flags) {
+	if (flags != 0) {
+		return errno = ENOSYS, -1;
+	}
+	return read(sockfd, buf, len);
+}
+
+int getsockopt(int, int, int, void *, socklen_t *) {
+	return errno = ENOSYS, -1;
+}
+
+int setsockopt(int, int, int, const void *, socklen_t) {
+	return 0;
+}
+
+int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
+	// TODO /net/ should expose local address somehow
+	/* dummy output, just to satisfy curl */
+	(void)sockfd; (void)addrlen;
+	addr->sa_family = AF_UNSPEC;
+	return 0;
+}
diff --git a/src/libc/socket.c b/src/libc/socket.c
deleted file mode 100644
index 5ea7266..0000000
--- a/src/libc/socket.c
+++ /dev/null
@@ -1,96 +0,0 @@
-#include <arpa/inet.h>
-#include <camellia.h>
-#include <camellia/syscalls.h>
-#include <errno.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <stdio.h>
-#include <sys/socket.h>
-
-int socket(int domain, int type, int protocol) {
-	if (domain != AF_INET || type != SOCK_STREAM || protocol != IPPROTO_TCP) {
-		return errno = ENOSYS, -1;
-	}
-	int h = _sys_getnull(0);
-	if (h < 0) {
-		return errno = -h, -1;
-	} else {
-		return h;
-	}
-}
-
-int bind(int, const struct sockaddr *, socklen_t) {
-	return errno = ENOSYS, -1;
-}
-
-int accept(int, struct sockaddr *, socklen_t *) {
-	return errno = ENOSYS, -1;
-}
-
-int listen(int, int) {
-	return errno = ENOSYS, -1;
-}
-
-int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
-	char buf[256];
-	struct sockaddr_in *addr4 = (void*)addr;
-	uint32_t ip;
-	uint16_t port;
-	int newfd;
-
-	if (addr->sa_family != AF_INET) {
-		return errno = ENOSYS, -1;
-	}
-
-	if (addrlen < (ssize_t)sizeof(*addr4)) {
-		return errno = EINVAL, -1;
-	}
-
-	ip   = ntohl(addr4->sin_addr.s_addr);
-	port = ntohs(addr4->sin_port);
-	if (snprintf(buf, 256, "/net/connect/0/%ld/tcp/%d", ip, port) >= 256) {
-		return errno = EGENERIC, -1;
-	}
-	newfd = camellia_open(buf, OPEN_READ | OPEN_WRITE);
-	if (newfd < 0) {
-		return -1;
-	}
-	dup2(newfd, sockfd);
-	close(newfd);
-	return 0;
-}
-
-ssize_t send(int sockfd, const void *buf, size_t len, int flags) {
-	if (flags != 0) {
-		return errno = ENOSYS, -1;
-	}
-	return write(sockfd, buf, len);
-}
-
-ssize_t recv(int sockfd, void *buf, size_t len, int flags) {
-	if (flags != 0) {
-		return errno = ENOSYS, -1;
-	}
-	return read(sockfd, buf, len);
-}
-
-int getsockopt(int, int, int, void *, socklen_t *) {
-	return errno = ENOSYS, -1;
-}
-
-int setsockopt(int, int, int, const void *, socklen_t) {
-	return 0;
-}
-
-int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
-	// TODO /net/ should expose local address somehow
-	/* dummy output, just to satisfy curl */
-	(void)sockfd; (void)addrlen;
-	addr->sa_family = AF_UNSPEC;
-	return 0;
-}
-
-struct hostent *gethostbyname(const char *name) {
-	(void)name;
-	return NULL;
-}
diff --git a/sysroot/usr/share/hosts b/sysroot/usr/share/hosts
new file mode 100644
index 0000000..54710a0
--- /dev/null
+++ b/sysroot/usr/share/hosts
@@ -0,0 +1,8 @@
+127.0.0.1	localhost
+
+104.18.114.97	cloudflare.com icanhazip.com dzwdz.net
+
+# friends etc
+104.248.107.166	tilde.town
+88.99.244.36 sortix.org
+88.99.244.4 irc.sortix.org
-- 
cgit v1.2.3