diff --git a/kernel-src/include/kernel/abi.h b/kernel-src/include/kernel/abi.h index f07f0716..494d0e5b 100644 --- a/kernel-src/include/kernel/abi.h +++ b/kernel-src/include/kernel/abi.h @@ -92,6 +92,7 @@ typedef struct { #define SO_BROADCAST 6 #define SO_BINDTODEVICE 25 +#define SO_KEEPALIVE 9 #define SOL_SOCKET 1 diff --git a/kernel-src/include/kernel/sock.h b/kernel-src/include/kernel/sock.h index 5122112c..ddca5f17 100644 --- a/kernel-src/include/kernel/sock.h +++ b/kernel-src/include/kernel/sock.h @@ -37,8 +37,11 @@ typedef struct socketops_t { int (*connect)(socket_t *socket, sockaddr_t *addr, uintmax_t data); int (*listen)(socket_t *socket, int backlog); int (*accept)(socket_t *server, socket_t *client, sockaddr_t *addr, uintmax_t flags); + int (*getname)(socket_t *socket, sockaddr_t *addr); + int (*getpeername)(socket_t *socket, sockaddr_t *addr); size_t (*datacount)(socket_t *socket); void (*destroy)(socket_t *socket); + int (*setopt)(socket_t *socket, int optname, void *buffer, size_t len); } socketops_t; typedef struct { @@ -117,6 +120,7 @@ static inline void sock_freemsghdr(msghdr_t *hdr) { } void localsock_leavebinding(vnode_t *vnode); +int localsock_pair(socket_t **ret1, socket_t **ret2); socket_t *localsock_createsocket(); socket_t *udp_createsocket(); socket_t *tcp_createsocket(); diff --git a/kernel-src/io/net/localsocket.c b/kernel-src/io/net/localsocket.c index f637f742..0eeb04be 100644 --- a/kernel-src/io/net/localsocket.c +++ b/kernel-src/io/net/localsocket.c @@ -11,7 +11,6 @@ struct localpair_t; struct binding_t; typedef struct { socket_t socket; - char *bindpath; ringbuffer_t ringbuffer; // shared with pair // client/connected server struct localpair_t *pair; @@ -21,6 +20,7 @@ typedef struct { int backlogsize; // shared with binding uintmax_t backlogcurrentwrite; // shared with binding uintmax_t backlogcurrentread; // shared with binding + char *bindpath; } localsocket_t; // created by the client socket @@ -689,6 +689,7 @@ static int localsock_bind(socket_t *socket, sockaddr_t *addr) { vnode->socketbinding = binding; VOP_UNLOCK(vnode); localsocket->binding = binding; + localsocket->bindpath = path; cleanup: if (error) { @@ -738,6 +739,52 @@ void localsock_leavebinding(vnode_t *vnode) { vnode->socketbinding = NULL; } +int localsock_pair(socket_t **ret1, socket_t **ret2) { + socket_t *socket1 = socket_create(SOCKET_TYPE_LOCAL); + if (socket1 == NULL) + return ENOMEM; + + socket_t *socket2 = socket_create(SOCKET_TYPE_LOCAL); + if (socket2 == NULL) { + localsock_destroy(socket1); + return ENOMEM; + } + + localpair_t *pair = alloc(sizeof(localpair_t)); + if (pair == NULL) { + localsock_destroy(socket1); + localsock_destroy(socket2); + return ENOMEM; + } + + MUTEX_INIT(&pair->mutex); + pair->server = (localsocket_t *)socket1; + pair->client = (localsocket_t *)socket2; + ((localsocket_t *)socket1)->pair = pair; + ((localsocket_t *)socket2)->pair = pair; + + *ret1 = socket1; + *ret2 = socket2; + return 0; +} + +static int localsock_getname(socket_t *socket, sockaddr_t *addr) { + localsocket_t *localsocket = (localsocket_t *)socket; + MUTEX_ACQUIRE(&socket->mutex, false); + if (localsocket->bindpath) + strcpy(addr->path, localsocket->bindpath); + else + addr->path[0] = '\0'; + + MUTEX_RELEASE(&socket->mutex); + return 0; +} + +static int localsock_getpeername(socket_t *socket, sockaddr_t *addr) { + addr->path[0] = '\0'; + return 0; +} + static socketops_t socketops = { .bind = localsock_bind, .listen = localsock_listen, @@ -747,7 +794,9 @@ static socketops_t socketops = { .recv = localsock_recv, .destroy = localsock_destroy, .poll = localsock_poll, - .datacount = localsocket_datacount + .datacount = localsocket_datacount, + .getname = localsock_getname, + .getpeername = localsock_getpeername }; socket_t *localsock_createsocket() { diff --git a/kernel-src/io/net/tcp.c b/kernel-src/io/net/tcp.c index d6d70f2d..0cd841ba 100644 --- a/kernel-src/io/net/tcp.c +++ b/kernel-src/io/net/tcp.c @@ -5,7 +5,7 @@ #include #include -#define WORKER_COUNT 8 +#define WORKER_COUNT 12 #define WORKER_BUFFER_SIZE (64 * 1024) #define WORKER_INTERNAL_BUFFER_SIZE 2048 // MSS will be min(_MSS_LIMIT, mtu - sizeof(ipv4header_t) - sizeof(tcpheader_t)) @@ -414,19 +414,16 @@ void tcp_process(netdev_t *netdev, void *buffer, ipv4frame_t *ipv4frame) { }; if (checksum(&ipv4pseudoheader, buffer) != 0) { - printf("tcp: bad checksum\n"); return; } if (be_to_cpu_w(ipv4pseudoheader.length) > WORKER_INTERNAL_BUFFER_SIZE) { - printf("tcp: packet too big for internal buffer size\n"); return; } int tasktype = TASK_TYPE_PACKET; tcpworker_t *worker = getworker(ipv4pseudoheader.length, tasktype); if (worker == NULL) { - printf("tcp: no free workers to handle packet\n"); return; } @@ -1413,7 +1410,9 @@ static int tcp_poll(socket_t *socket, polldata_t *data, int events) { static int tcp_bind(socket_t *socket, sockaddr_t *addr) { tcpsocket_t *tcpsocket = (tcpsocket_t *)socket; - __assert(addr->ipv4addr.addr == 0); + if (addr->ipv4addr.addr != 0) { + printf("tcp: bind tried to bind to non zero address %x\n", addr->ipv4addr.addr); + } MUTEX_ACQUIRE(&socket->mutex, false); tcb_t *tcb = tcpsocket->tcb; if (tcb == NULL) { @@ -1741,6 +1740,67 @@ static void tcp_destroy(socket_t *socket) { free(socket); } +static int tcp_getname(socket_t *socket, sockaddr_t *addr) { + tcpsocket_t *tcpsocket = (tcpsocket_t *)socket; + MUTEX_ACQUIRE(&socket->mutex, false); + tcb_t *tcb = tcpsocket->tcb; + + if (tcb) { + MUTEX_ACQUIRE(&tcb->mutex, false); + + addr->ipv4addr.addr = 0; + addr->ipv4addr.port = tcb->port; + + MUTEX_RELEASE(&tcb->mutex); + } else { + addr->ipv4addr.addr = 0; + addr->ipv4addr.port = 0; + } + + MUTEX_RELEASE(&socket->mutex); + return 0; +} + +static int tcp_getpeername(socket_t *socket, sockaddr_t *addr) { + tcpsocket_t *tcpsocket = (tcpsocket_t *)socket; + MUTEX_ACQUIRE(&socket->mutex, false); + tcb_t *tcb = tcpsocket->tcb; + + if (tcb) { + MUTEX_ACQUIRE(&tcb->mutex, false); + + addr->ipv4addr.addr = tcb->key.peer; + addr->ipv4addr.port = tcb->key.peerport; + + MUTEX_RELEASE(&tcb->mutex); + } else { + addr->ipv4addr.addr = 0; + addr->ipv4addr.port = 0; + } + + MUTEX_RELEASE(&socket->mutex); + return 0; +} + +// called with socket locked +static int tcp_setopt(socket_t *socket, int optname, void *buffer, size_t len) { + tcpsocket_t *tcpsocket = (tcpsocket_t *)socket; + tcb_t *tcb = tcpsocket->tcb; + + if (tcb) { + MUTEX_ACQUIRE(&tcb->mutex, false); + + switch (optname) { + case SO_KEEPALIVE: + // TODO this one + break; + } + + MUTEX_RELEASE(&tcb->mutex); + } + return 0; +} + static socketops_t socketops = { .bind = tcp_bind, .send = tcp_send, @@ -1750,7 +1810,10 @@ static socketops_t socketops = { .listen = tcp_listen, .accept = tcp_accept, .datacount = tcp_datacount, - .destroy = tcp_destroy + .destroy = tcp_destroy, + .getname = tcp_getname, + .getpeername = tcp_getpeername, + .setopt = tcp_setopt }; socket_t *tcp_createsocket() { diff --git a/kernel-src/io/net/udp.c b/kernel-src/io/net/udp.c index 530bcd0e..4d00d3e3 100644 --- a/kernel-src/io/net/udp.c +++ b/kernel-src/io/net/udp.c @@ -293,6 +293,24 @@ static void udp_destroy(socket_t *socket) { free(socket); } +static int udp_getname(socket_t *socket, sockaddr_t *addr) { + udpsocket_t *udpsocket = (udpsocket_t *)socket; + MUTEX_ACQUIRE(&socket->mutex, false); + addr->ipv4addr.addr = udpsocket->address; + addr->ipv4addr.port = udpsocket->port; + MUTEX_RELEASE(&socket->mutex); + return 0; +} + +static int udp_getpeername(socket_t *socket, sockaddr_t *addr) { + udpsocket_t *udpsocket = (udpsocket_t *)socket; + MUTEX_ACQUIRE(&socket->mutex, false); + addr->ipv4addr.addr = udpsocket->peeraddress; + addr->ipv4addr.port = udpsocket->peerport; + MUTEX_RELEASE(&socket->mutex); + return 0; +} + static int udp_poll(socket_t *socket, polldata_t *data, int events) { int revents = 0; MUTEX_ACQUIRE(&socket->mutex, false); @@ -308,7 +326,9 @@ static socketops_t socketops = { .send = udp_send, .recv = udp_recv, .destroy = udp_destroy, - .poll = udp_poll + .poll = udp_poll, + .getname = udp_getname, + .getpeername = udp_getpeername }; socket_t *udp_createsocket() { @@ -321,6 +341,7 @@ socket_t *udp_createsocket() { free(socket); return NULL; } + SPINLOCK_INIT(socket->ringbufferlock); socket->socket.ops = &socketops; diff --git a/kernel-src/sys/syscalls/setsockopt.c b/kernel-src/sys/syscalls/setsockopt.c index df17faa5..c035d3aa 100644 --- a/kernel-src/sys/syscalls/setsockopt.c +++ b/kernel-src/sys/syscalls/setsockopt.c @@ -41,7 +41,7 @@ syscallret_t syscall_setsockopt(context_t *, int fd, int level, int optname, voi MUTEX_ACQUIRE(&socket->mutex, false); switch (optname) { - case SO_BINDTODEVICE: + case SO_BINDTODEVICE: { if (val) { socket->netdev = netdev_getdev(val); ret.errno = socket->netdev ? 0 : ENODEV; @@ -49,7 +49,8 @@ syscallret_t syscall_setsockopt(context_t *, int fd, int level, int optname, voi socket->netdev = NULL; } break; - case SO_BROADCAST: + } + case SO_BROADCAST: { if (val == NULL) { ret.errno = EFAULT; } else { @@ -57,6 +58,14 @@ syscallret_t syscall_setsockopt(context_t *, int fd, int level, int optname, voi ret.errno = 0; } break; + } + case SO_KEEPALIVE: { + if (val == NULL) + ret.errno = EFAULT; + else + ret.errno = socket->ops->setopt ? socket->ops->setopt(socket, optname, buffer, len) : ENOPROTOOPT; + break; + } default: ret.errno = ENOPROTOOPT; }