// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-FileCopyrightText: 2020-2021 Alyssa Ross #define _GNU_SOURCE #include "vsock.h" #include #include #include #include static void fill_sockaddr(struct sockaddr_vm *addr, uint32_t cid, uint32_t port) { addr->svm_family = AF_VSOCK; addr->svm_cid = cid; addr->svm_port = port; } static int fill_cid_and_port(const struct sockaddr_vm *addr, uint32_t *cid, uint32_t *port) { // Check that this sockaddr info is actually for the socket // type we think it is, or we could get some very confusing // data out of it. if (addr->svm_family != AF_VSOCK) { errno = EPROTOTYPE; return -1; } if (cid) *cid = addr->svm_cid; if (port) *port = addr->svm_port; return 0; } int vsock_bind(int fd, uint32_t cid, uint32_t port) { struct sockaddr_vm addr = { 0 }; fill_sockaddr(&addr, cid, port); if (bind(fd, (struct sockaddr *)&addr, sizeof addr) == -1) return -1; return 0; } int vsock_accept(int sockfd, uint32_t *cid, uint32_t *port) { struct sockaddr_vm addr = { 0 }; socklen_t addr_size = sizeof addr; int fd; if ((fd = accept(sockfd, (struct sockaddr *)&addr, &addr_size)) == -1) return -1; if (fill_cid_and_port(&addr, cid, port) == -1) return -1; return fd; } int vsock_connect(int fd, uint32_t cid, uint32_t port) { struct sockaddr_vm addr = { 0 }; fill_sockaddr(&addr, cid, port); return connect(fd, (struct sockaddr *)&addr, sizeof addr); } int vsock_open(uint32_t cid, uint32_t port) { int fd = socket(AF_VSOCK, SOCK_STREAM, 0); if (fd == -1) return -1; if (vsock_connect(fd, cid, port) == -1) return -1; return fd; } int vsock_get_cid_and_port(int fd, uint32_t *cid, uint32_t *port) { struct sockaddr_vm addr; socklen_t addrlen = sizeof addr; if (getsockname(fd, (struct sockaddr *)&addr, &addrlen) == -1) return -1; return fill_cid_and_port(&addr, cid, port); }