#include #include #include #include #include #include #include #include #include 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 the local address somehow /* Outputs a fake address, just to satisfy curl. * Can't be AF_UNSPEC, as curl tries to print it with inet_ntop. */ (void)sockfd; struct sockaddr_in dummy = { .sin_family = AF_INET, .sin_port = 0, .sin_addr = {0}, }; if ((int)sizeof(dummy) < *addrlen) { *addrlen = sizeof(dummy); } else if (*addrlen < 0) { return errno = EINVAL, -1; } memcpy(addr, &dummy, *addrlen); return 0; }