diff --git a/arch/x86_64.c b/arch/x86_64.c index 6016171..7925f17 100644 --- a/arch/x86_64.c +++ b/arch/x86_64.c @@ -88,4 +88,108 @@ int fsync(unsigned int fd) { return rtn; } +#define SYS_SOCKET 41 +int socket(int domain, int type, int protocol) { + int32_t fd; + asm volatile ( + "syscall\n" + : "=a"(fd) + : "a"(SYS_SOCKET), "D"(domain), "S"(type), "d"(protocol) + : "rcx", "r11" + ); + return fd; +} + +#define SYS_SETSOCKOPT 54 +int setsockopt(int fd, int level, int optname, const void* optval, uint64_t optlen) { + int rtn; + asm volatile( + "mov %5, %%r10\n" + "mov %6, %%r8\n" + "syscall\n" + : "=a"(rtn) + : "a"(SYS_SETSOCKOPT), "D"(fd), "S"(level), "d"(optname), "r"(optval), "r"(optlen) + : "rcx", "r11" + ); + return rtn; +} + +#define SYS_BIND 49 +int bind(int fd, const void* sockaddr, uint64_t addrlen) { + int rtn; + asm volatile( + "syscall\n" + : "=a"(rtn) + : "a"(SYS_BIND), "D"(fd), "S"(sockaddr), "d"(addrlen) + : "rcx", "r11" + ); + return rtn; +} + +#define SYS_LISTEN 50 +int listen(int fd, int backlog) { + int rtn; + asm volatile( + "syscall\n" + : "=a"(rtn) + : "a"(SYS_LISTEN), "D"(fd), "S"(backlog) + : "rcx", "r11" + ); + return rtn; +} + +#define SYS_ACCEPT 43 +int accept(int fd, void* addr, uint64_t* addrlen) { + int rtn; + asm volatile( + "syscall\n" + : "=a"(rtn) + : "a"(SYS_ACCEPT), "D"(fd), "S"(addr), "d"(addrlen) + : "rcx", "r11", "memory" + ); + return rtn; +} + +#define SYS_CONNECT 42 +int connect(int fd, void* addr, uint64_t addrlen) { + int rtn; + asm volatile( + "syscall\n" + : "=a"(rtn) + : "a"(SYS_CONNECT), "D"(fd), "S"(addr), "d"(addrlen) + : "rcx", "r11" + ); + return rtn; +} + +#define SYS_SENDTO 44 +int64_t sendto(int fd, const void* buf, uint64_t size, int flags, const void* sockaddr, uint64_t addrlen) { + int64_t nsent; + asm volatile( + "mov %5, %%r10\n" + "mov %6, %%r8\n" + "mov %7, %%r9\n" + "syscall\n" + : "=a"(nsent) + : "a"(SYS_SENDTO), "D"(fd), "S"(buf), "d"(size), "r"((int64_t)flags), "r"(sockaddr), "r"(addrlen) + : "rcx", "r11" + ); + return nsent; +} + +#define SYS_RECVFROM 45 +int64_t recvfrom(int fd, const void* buf, uint64_t size, int flags, const void* sockaddr, uint64_t addrlen) { + int64_t nrecv; + asm volatile( + "mov %5, %%r10\n" + "mov %6, %%r8\n" + "mov %7, %%r9\n" + "syscall\n" + : "=a"(nrecv) + : "a"(SYS_RECVFROM), "D"(fd), "S"(buf), "d"(size), "r"((int64_t)flags), "r"(sockaddr), "r"(addrlen) + : "rcx", "r11", "memory" + ); + return nrecv; +} + #endif /* ifdef __x86_64__ */ diff --git a/int.h b/int.h index f7bb71b..550e198 100644 --- a/int.h +++ b/int.h @@ -56,6 +56,7 @@ typedef uint32_t uintptr_t; #endif #endif -//TODO: -//#ifdef __SIZEOF_SIZE_T__ +// TODO: +// size_t, ssize_t, socklen_t +// #ifdef __SIZEOF_SIZE_T__ #endif // !MINIMALINT_H diff --git a/socktest.c b/socktest.c new file mode 100644 index 0000000..8555713 --- /dev/null +++ b/socktest.c @@ -0,0 +1,92 @@ +#include "sys.h" +#include "int.h" +#include "net/ipv4.h" + +int main() { + char recvBuff[4096]; + int socket_fd, connection_fd; + int c; + struct sockaddr_in server, client; + server.sin_family = AF_INET; + server.sin_addr.s_addr = INADDR_ANY; + //server.sin_port = htons( 6969 ); + server.sin_port = 0x391b; + + // Create the socket + socket_fd = socket(AF_INET, SOCK_STREAM, 0); + if (socket_fd < 0) { + write(STDERR, "Socket error\n", 13); + close(socket_fd); + return(1); + } + + // Set socket options + int opt = 1; + if(0 > setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) { + write(STDERR, "Socket error\n", 13); + close(socket_fd); + return(2); + } + + // Bind the socket + if( bind(socket_fd, (struct sockaddr *)&server, sizeof(server)) < 0) { + write(STDERR, "Socket error\n", 13); + close(socket_fd); + return(3); + } + + // Listen for incoming connections + if (listen(socket_fd, 3) < 0) { + return 4; + } + write(STDOUT, "Waiting for incoming connections...\n", 36); + + // Get the new connection + c = sizeof(struct sockaddr_in); + connection_fd = accept(socket_fd, (void *)&client, (uint64_t*)&c); + write(STDOUT, "Got new connection\n", 19); + if(connection_fd < 0) { + write(STDERR, "Connection error\n", 17); + close(connection_fd); + close(socket_fd); + return(5); + } + + + //char *client_ip = inet_ntoa(client.sin_addr); + //int client_port = ntohs(client.sin_port); + //printf("Connection accepted from %s:%d\n", client_ip, client_port); + + // Send stuff + write(STDOUT, "Connection Established!\n", 24); + if( send(connection_fd, "Connection Established!\n", 24, 0) < 0) { + write(STDERR, "Connection error\n", 17); + close(connection_fd); + close(socket_fd); + return(6); + } + + // Recieve stuff + write(STDOUT, "Recieving data...\n", 18); + for(;;) { + int64_t incoming = recv(connection_fd, recvBuff, 4096, 0); + if( incoming < 0) { + write(STDERR, "Connection error\n", 17); + close(connection_fd); + close(socket_fd); + return(7); + }if(incoming == 0) break; + + // Print the recieved data + write(STDOUT, recvBuff, incoming); + } + + write(STDOUT, "Closing connection\n", 19); + close(connection_fd); + close(socket_fd); + return 0; +} + +void _start() { + exit(main()); +} diff --git a/sys.h b/sys.h index 8d2237f..b12881f 100644 --- a/sys.h +++ b/sys.h @@ -37,6 +37,70 @@ int32_t openat(int32_t fd, const char* filename, uint32_t flags, uint32_t mode); int close(unsigned int fd); int fsync(unsigned int fd); +// Socket syscalls +int socket(int domain, int type, int protocol); +int setsockopt(int sockfd, int level, int optname, const void* optval, uint64_t optlen); +int bind(int sockfd, const void* sockaddr, uint64_t addrlen); +int listen(int fd, int backlog); +int accept(int sockfd, void* addr, uint64_t* addrlen); +int connect(int sockfd, void* addr, uint64_t addrlen); +int64_t sendto(int sockfd, const void* buf, uint64_t size, int flags, const void* sockaddr, uint64_t addrlen); +#define send(sockfd, buf, size, flags) sendto(sockfd, buf, size, flags, 0, 0) +int64_t recvfrom(int sockfd, const void* buf, uint64_t size, int flags, const void* sockaddr, uint64_t addrlen); +#define recv(sockfd, buf, size, flags) recvfrom(sockfd, buf, size, flags, 0, 0) +// Socket Domain constants +typedef unsigned short sa_family_t; +/* Supported address families. */ +#define AF_UNIX 1 /* Unix domain sockets */ +#define AF_LOCAL 1 /* POSIX name for AF_UNIX */ +#define AF_INET 2 /* Internet IP Protocol */ +#define AF_AX25 3 /* Amateur Radio AX.25 */ +#define AF_INET6 10 /* IP version 6 */ +#define AF_ROSE 11 /* Amateur Radio X.25 PLP */ +#define AF_PACKET 17 /* Packet family */ +#define AF_CAN 29 /* Controller Area Network */ +#define AF_BLUETOOTH 31 /* Bluetooth sockets */ +// Socket type constants +enum sock_type { +SOCK_STREAM = 1, +SOCK_DGRAM = 2, +SOCK_RAW = 3, +SOCK_RDM = 4, +SOCK_SEQPACKET = 5, +SOCK_DCCP = 6, +SOCK_PACKET = 10, +}; + +#if defined(__mips__) + #define SOL_SOCKET 0xffff +#else + #define SOL_SOCKET 1 + + #define SO_DEBUG 1 + #define SO_REUSEADDR 2 + #define SO_TYPE 3 + #define SO_ERROR 4 + #define SO_DONTROUTE 5 + #define SO_BROADCAST 6 + #define SO_SNDBUF 7 + #define SO_RCVBUF 8 + #define SO_SNDBUFFORCE 32 + #define SO_RCVBUFFORCE 33 + #define SO_KEEPALIVE 9 + #define SO_OOBINLINE 10 + #define SO_NO_CHECK 11 + #define SO_PRIORITY 12 + #define SO_LINGER 13 + #define SO_BSDCOMPAT 14 + #define SO_REUSEPORT 15 + #define SO_PASSCRED 16 + #define SO_PEERCRED 17 + #define SO_RCVLOWAT 18 + #define SO_SNDLOWAT 19 + #define SO_RCVTIMEO 20 + #define SO_SNDTIMEO 21 +#endif + uint32_t fork(); // Provide memset for clang