summaryrefslogtreecommitdiff
path: root/userland
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2024-06-20 23:13:51 +0200
committerAnton Kling <anton@kling.gg>2024-06-20 23:13:51 +0200
commit9725791024d159ba0c5b6e8eef13a0e9077523a9 (patch)
tree91555c2f74e3d0794964f9f9cbb948b62550e46b /userland
parentd7f2c29a6b238d678c6f76237b35b14eda258e7d (diff)
Add getaddrinfo and change other libc stuff
Diffstat (limited to 'userland')
-rw-r--r--userland/libc/Makefile4
-rw-r--r--userland/libc/include/netdb.h7
-rw-r--r--userland/libc/include/unistd.h2
-rw-r--r--userland/libc/netdb/getaddrinfo.c239
-rw-r--r--userland/libc/unistd/lseek.c4
-rw-r--r--userland/libc/unistd/write.c3
6 files changed, 253 insertions, 6 deletions
diff --git a/userland/libc/Makefile b/userland/libc/Makefile
index 2d301cb..2be101e 100644
--- a/userland/libc/Makefile
+++ b/userland/libc/Makefile
@@ -1,8 +1,8 @@
CC="i686-sb-gcc"
AR="i686-sb-ar"
AS="i686-sb-as"
-CFLAGS = -ggdb -ffreestanding -O0 -Wall -Wextra -pedantic -Werror -Wimplicit-fallthrough -I./include/ -static -I../../include/ -Wno-int-conversion -Wno-unused-parameter
-OBJ=crt0.o libc.o malloc/malloc.o pty.o sys/mman/mmap.o sys/mman/munmap.o memset.o assert.o stdio/snprintf.o stdio/vfprintf.o string/memcpy.o string/memcmp.o string/strcmp.o ubsan.o string/strcpy.o isspace.o stdio/puts.o stdio/putchar.o dirent/opendir.o dirent/readdir.o dirent/closedir.o unistd/getopt.o dirent/scandir.o dirent/alphasort.o stdio/printf.o stdio/vdprintf.o stdio/vprintf.o stdio/dprintf.o stdio/vprintf.o string/strlen.o string/strnlen.o stdio/stdin.o stdio/getchar.o stdio/fgetc.o arpa/inet/htons.o arpa/inet/htonl.o stdio/fread.o stdio/fwrite.o stdio/fopen.o stdio/fclose.o stdio/fseek.o ctype/isascii.o stdio/fprintf.o stdlib/atoi.o stdlib/strtol.o ctype/toupper.o ctype/tolower.o string/strcat.o string/strchr.o string/sscanf.o sys/stat/stat.o stdlib/getenv.o string/strrchr.o stdio/ftell.o stdio/tmpfile.o stdio/fgets.o stdio/feof.o stdio/fscanf.o stdio/ungetc.o string/strncmp.o stdio/fputc.o string/strncpy.o stdio/remove.o stdio/ferror.o stdio/fputs.o stdlib/rand.o stdlib/srand.o unistd/getpid.o stdlib/strtoul.o stdio/fflush.o stdlib/abort.o string/strcspn.o time/localtime.o time/time.o time/clock_gettime.o time/gmtime.o time/strftime.o string/strpbrk.o ctype/isdigit.o ctype/isalpha.o ctype/isxdigit.o ctype/ispunct.o stdio/setvbuf.o stdio/fileno.o stdio/putc.o stdio/sprintf.o stdlib/abs.o string/strspn.o stdlib/qsort.o string/memmove.o setjmp/longjmp.o setjmp/setjmp.o libgen/basename.o string/strdup.o string/strndup.o string/strlcpy.o stdlib/atexit.o stdio/open_memstream.o libgen/dirname.o unistd/unlink.o string/strstr.o string/strcasecmp.o string/strncasecmp.o stdlib/mkstemp.o string/strtok.o unistd/execvp.o unistd/_exit.o ctype/isalnum.o time/ctime_r.o stdlib/strtold.o sys/time/gettimeofday.o stdio/fgetpos.o stdio/fsetpos.o ctype/isprint.o stdlib/system.o stdio/tmpnam.o unistd/msleep.o stdlib/atof.o stdlib/strtod.o stdio/rename.o sys/stat/mkdir.o unistd/uptime.o unistd/ftruncate.o sys/socket/recvfrom.o sys/socket/sendto.o signal/kill.o signal/sigaction.o unistd/chdir.o unistd/getcwd.o stdio/getdelim.o stdio/getline.o unistd/isatty.o sys/socket/listen.o stdlib/realpath.o systemcall.o sys/random/randomfill.o fcntl/open.o unistd/write.o unistd/pwrite.o fcntl/open_process.o tb/sb.o tb/sv.o string/memchr.o stdlib/atol.o stdlib/atoll.o stdlib/strtoll.o sys/stat/fstat.o unistd/lseek.o ctype/isupper.o ctype/islower.o ctype/isblank.o ctype/isgraph.o ctype/iscntrl.o math/ldexp.o sys/socket/connect.o sys/socket/setsockopt.o
+CFLAGS = -ggdb -ffreestanding -nostdlib -O0 -Wall -Wextra -pedantic -Werror -Wimplicit-fallthrough -I./include/ -static -I../../include/ -Wno-int-conversion -Wno-unused-parameter
+OBJ=crt0.o libc.o malloc/malloc.o pty.o sys/mman/mmap.o sys/mman/munmap.o memset.o assert.o stdio/snprintf.o stdio/vfprintf.o string/memcpy.o string/memcmp.o string/strcmp.o ubsan.o string/strcpy.o isspace.o stdio/puts.o stdio/putchar.o dirent/opendir.o dirent/readdir.o dirent/closedir.o unistd/getopt.o dirent/scandir.o dirent/alphasort.o stdio/printf.o stdio/vdprintf.o stdio/vprintf.o stdio/dprintf.o stdio/vprintf.o string/strlen.o string/strnlen.o stdio/stdin.o stdio/getchar.o stdio/fgetc.o arpa/inet/htons.o arpa/inet/htonl.o stdio/fread.o stdio/fwrite.o stdio/fopen.o stdio/fclose.o stdio/fseek.o ctype/isascii.o stdio/fprintf.o stdlib/atoi.o stdlib/strtol.o ctype/toupper.o ctype/tolower.o string/strcat.o string/strchr.o string/sscanf.o sys/stat/stat.o stdlib/getenv.o string/strrchr.o stdio/ftell.o stdio/tmpfile.o stdio/fgets.o stdio/feof.o stdio/fscanf.o stdio/ungetc.o string/strncmp.o stdio/fputc.o string/strncpy.o stdio/remove.o stdio/ferror.o stdio/fputs.o stdlib/rand.o stdlib/srand.o unistd/getpid.o stdlib/strtoul.o stdio/fflush.o stdlib/abort.o string/strcspn.o time/localtime.o time/time.o time/clock_gettime.o time/gmtime.o time/strftime.o string/strpbrk.o ctype/isdigit.o ctype/isalpha.o ctype/isxdigit.o ctype/ispunct.o stdio/setvbuf.o stdio/fileno.o stdio/putc.o stdio/sprintf.o stdlib/abs.o string/strspn.o stdlib/qsort.o string/memmove.o setjmp/longjmp.o setjmp/setjmp.o libgen/basename.o string/strdup.o string/strndup.o string/strlcpy.o stdlib/atexit.o stdio/open_memstream.o libgen/dirname.o unistd/unlink.o string/strstr.o string/strcasecmp.o string/strncasecmp.o stdlib/mkstemp.o string/strtok.o unistd/execvp.o unistd/_exit.o ctype/isalnum.o time/ctime_r.o stdlib/strtold.o sys/time/gettimeofday.o stdio/fgetpos.o stdio/fsetpos.o ctype/isprint.o stdlib/system.o stdio/tmpnam.o unistd/msleep.o stdlib/atof.o stdlib/strtod.o stdio/rename.o sys/stat/mkdir.o unistd/uptime.o unistd/ftruncate.o sys/socket/recvfrom.o sys/socket/sendto.o signal/kill.o signal/sigaction.o unistd/chdir.o unistd/getcwd.o stdio/getdelim.o stdio/getline.o unistd/isatty.o sys/socket/listen.o stdlib/realpath.o systemcall.o sys/random/randomfill.o fcntl/open.o unistd/write.o unistd/pwrite.o fcntl/open_process.o tb/sb.o tb/sv.o string/memchr.o stdlib/atol.o stdlib/atoll.o stdlib/strtoll.o sys/stat/fstat.o unistd/lseek.o ctype/isupper.o ctype/islower.o ctype/isblank.o ctype/isgraph.o ctype/iscntrl.o math/ldexp.o sys/socket/connect.o sys/socket/setsockopt.o arpa/inet/ntohl.o arpa/inet/ntohs.o netdb/getaddrinfo.o
all: libc.a
%.o: %.c
diff --git a/userland/libc/include/netdb.h b/userland/libc/include/netdb.h
index e69de29..4b4dc99 100644
--- a/userland/libc/include/netdb.h
+++ b/userland/libc/include/netdb.h
@@ -0,0 +1,7 @@
+#include <arpa/inet.h>
+#include <sys/socket.h>
+
+int getaddrinfo(const char *restrict node, const char *restrict service,
+ const struct addrinfo *restrict hints,
+ struct addrinfo **restrict res);
+void freeaddrinfo(struct addrinfo *res);
diff --git a/userland/libc/include/unistd.h b/userland/libc/include/unistd.h
index f3e0f28..b44ca3e 100644
--- a/userland/libc/include/unistd.h
+++ b/userland/libc/include/unistd.h
@@ -30,5 +30,5 @@ int pread(int fd, void *buf, size_t count, size_t offset);
int fork(void);
int write(int fd, const char *buf, size_t count);
int pwrite(int fd, const char *buf, size_t count, size_t offset);
-off_t lseek(int fildes, off_t offset, int whence);
+int lseek(int fildes, int offset, int whence);
#endif
diff --git a/userland/libc/netdb/getaddrinfo.c b/userland/libc/netdb/getaddrinfo.c
new file mode 100644
index 0000000..d550b39
--- /dev/null
+++ b/userland/libc/netdb/getaddrinfo.c
@@ -0,0 +1,239 @@
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <tb/sv.h>
+#include <arpa/inet.h>
+#include <assert.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#define PORT 53
+
+u16 add_domain_label(u8 *buffer, struct sv label) {
+ assert(label.length < 64);
+ u16 size = 0;
+ u8 ll = label.length;
+ memcpy(buffer + size, &ll, sizeof(u8));
+ size += sizeof(u8);
+ memcpy(buffer + size, label.s, label.length);
+ size += label.length;
+ return size;
+}
+
+u16 send_domain_request(int sockfd, const char *domain, u16 *id) {
+ *id = 0;
+ u8 message[512];
+ memset(message, 0, sizeof(message));
+
+ u16 size = 0;
+ size += 6 * sizeof(u16); // header
+
+ u16 flags = htons(0x0100);
+ u16 qdcount = htons(1);
+ memcpy(message, id, sizeof(u16));
+ memcpy(message + sizeof(u16), &flags, sizeof(u16));
+ memcpy(message + sizeof(u16) * 2, &qdcount, sizeof(u16));
+
+ struct sv labels = C_TO_SV(domain);
+ for (; !sv_isempty(labels);) {
+ struct sv label = sv_split_delim(labels, &labels, '.');
+ size += add_domain_label(message + size, label);
+ }
+
+ size += add_domain_label(message + size, C_TO_SV(""));
+
+ u16 query_type = htons(1); // A type
+ memcpy(message + size, &query_type, sizeof(u16));
+ size += sizeof(u16);
+
+ u16 q_class = htons(1); // IN
+ memcpy(message + size, &q_class, sizeof(u16));
+ size += sizeof(u16);
+
+ printf("sending: %d\n", size);
+
+ write(sockfd, (char *)message, size);
+ return size;
+}
+
+int connect_dns(void) {
+ int sockfd;
+ struct sockaddr_in servaddr;
+
+ memset(&servaddr, 0, sizeof(servaddr));
+ servaddr.sin_addr.a[0] = 8;
+ servaddr.sin_addr.a[1] = 8;
+ servaddr.sin_addr.a[2] = 8;
+ servaddr.sin_addr.a[3] = 8;
+ servaddr.sin_port = htons(PORT);
+ servaddr.sin_family = AF_INET;
+
+ sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+
+ if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
+ return -1;
+ }
+ return sockfd;
+}
+
+/*
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = type;
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_protocol = 0;
+ hints.ai_canonname = NULL;
+ hints.ai_addr = NULL;
+ hints.ai_next = NULL;
+*/
+
+#define EAI_AGAIN 1
+#define EAI_FAIL 2
+#define EAI_NONAME 3
+#define EAI_MEMORY 4
+
+u16 service_to_port(const char *service) {
+ int is_number = 0;
+ for (int i = 0; service[i]; i++) {
+ if (isdigit(service[i])) {
+ is_number = 1;
+ }
+ }
+ if (is_number) {
+ return htons(atoi(service));
+ }
+
+#define SERVICE(_name, _port) \
+ if (0 == strcmp(_name, service)) { \
+ return htons(_port); \
+ }
+ SERVICE("http", 80)
+ SERVICE("https", 443)
+#undef SERVICE
+ return 0;
+}
+
+int getaddrinfo(const char *restrict node, const char *restrict service,
+ const struct addrinfo *restrict hints,
+ struct addrinfo **restrict res) {
+ int sockfd = connect_dns();
+ if (-1 == sockfd) {
+ return EAI_AGAIN;
+ }
+
+ // TODO: Use the hints to make decisions about what data to request.
+ (void)hints;
+
+ u16 id;
+ u16 size = send_domain_request(sockfd, node, &id);
+
+ u8 buffer[512];
+ memset(buffer, 0, sizeof(buffer));
+ int rc = read(sockfd, buffer, sizeof(buffer));
+ if (rc < size) {
+ close(sockfd);
+ return EAI_FAIL;
+ }
+
+ if (0 != memcmp(buffer, &id, sizeof(u16))) {
+ close(sockfd);
+ return EAI_FAIL;
+ }
+
+ u16 flags;
+ memcpy(&flags, buffer + sizeof(u16), sizeof(u16));
+ flags = ntohs(flags);
+
+ if (!(flags & (1 << 15))) { // QR
+ close(sockfd);
+ return EAI_FAIL;
+ }
+ if (0 != (flags & 0x1F)) { // Error field
+ close(sockfd);
+ return EAI_AGAIN;
+ }
+
+ u16 qcount = ntohs(*(u16 *)(buffer + sizeof(u16) * 2));
+ if (1 != qcount) {
+ close(sockfd);
+ return EAI_FAIL;
+ }
+
+ u16 ancount = ntohs(*(u16 *)(buffer + sizeof(u16) * 3));
+ if (1 != ancount) {
+ close(sockfd);
+ return EAI_NONAME; // TODO: Check if this is correct
+ }
+
+ u8 *answer = buffer + size;
+ u16 answer_length = rc - size;
+ if (0 == answer_length) {
+ close(sockfd);
+ return EAI_FAIL;
+ }
+
+ /*
+ // get labels
+ {
+ u16 offset = ntohs(*(u16 *)answer);
+ assert(3 == offset >> 14);
+ offset &= ~(3 << 14);
+
+ printf("offset: %d\n", offset);
+ printf("name: ");
+ u8 length = buffer[offset];
+ for (int i = 0; i < length; i++) {
+ printf("%c", buffer[offset + 1 + i]);
+ }
+ printf("\n");
+ }
+ */
+
+ // type
+ u16 type = ntohs(*(u16 *)(answer + sizeof(u16)));
+ u16 class = ntohs(*(u16 *)(answer + sizeof(u16) * 2));
+ if (1 != type) {
+ close(sockfd);
+ return EAI_FAIL;
+ }
+ if (1 != class) {
+ close(sockfd);
+ return EAI_FAIL;
+ }
+
+ u16 rdlength = ntohs(*(u16 *)(answer + sizeof(u16) * 3 + sizeof(u32)));
+
+ if (4 != rdlength) {
+ close(sockfd);
+ return EAI_FAIL;
+ }
+ u32 ip = *(u32 *)(answer + sizeof(u16) * 4 + sizeof(u32));
+
+ if (res) {
+ *res = calloc(1, sizeof(struct addrinfo));
+ if (!(*res)) {
+ close(sockfd);
+ return EAI_MEMORY;
+ }
+ struct sockaddr_in *sa = calloc(1, sizeof(struct sockaddr_in));
+ if (!sa) {
+ free(*res);
+ close(sockfd);
+ return EAI_MEMORY;
+ }
+ (*res)->ai_addr = (struct sockaddr *)sa;
+ sa->sin_addr.s_addr = ip;
+ sa->sin_port = service_to_port(service);
+ sa->sin_family = AF_INET;
+ }
+ close(sockfd);
+ return 0;
+}
+
+void freeaddrinfo(struct addrinfo *res) {
+ free(res->ai_addr);
+ free(res);
+}
diff --git a/userland/libc/unistd/lseek.c b/userland/libc/unistd/lseek.c
index 2dcd661..b9ebfae 100644
--- a/userland/libc/unistd/lseek.c
+++ b/userland/libc/unistd/lseek.c
@@ -1,7 +1,7 @@
#include <errno.h>
-#include <unistd.h>
#include <syscall.h>
+#include <unistd.h>
-off_t lseek(int fildes, off_t offset, int whence) {
+int lseek(int fildes, int offset, int whence) {
RC_ERRNO(syscall(SYS_LSEEK, (u32)fildes, offset, whence, 0, 0));
}
diff --git a/userland/libc/unistd/write.c b/userland/libc/unistd/write.c
index 661fb01..0dd1824 100644
--- a/userland/libc/unistd/write.c
+++ b/userland/libc/unistd/write.c
@@ -1,6 +1,7 @@
#include <syscall.h>
#include <unistd.h>
+#include <errno.h>
int write(int fd, const char *buf, size_t count) {
- return syscall(SYS_WRITE, fd, buf, count, 0, 0);
+ RC_ERRNO(syscall(SYS_WRITE, fd, buf, count, 0, 0));
}