socket: getname, getpeername, setopt

This commit is contained in:
Matheus
2024-06-04 22:44:37 -03:00
parent 7012f73283
commit b230d58a3f
6 changed files with 158 additions and 11 deletions
+1
View File
@@ -92,6 +92,7 @@ typedef struct {
#define SO_BROADCAST 6
#define SO_BINDTODEVICE 25
#define SO_KEEPALIVE 9
#define SOL_SOCKET 1
+4
View File
@@ -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();
+51 -2
View File
@@ -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() {
+69 -6
View File
@@ -5,7 +5,7 @@
#include <kernel/timekeeper.h>
#include <kernel/interrupt.h>
#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() {
+22 -1
View File
@@ -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;
+11 -2
View File
@@ -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;
}