// SPDX-License-Identifier: GPL-2.0-or-later /* PASST - Plug A Simple Socket Transport * for qemu/UNIX domain socket mode * * PASTA - Pack A Subtle Tap Abstraction * for network namespace/tap device mode * * PESTO - Programmable Extensible Socket Translation Orchestrator * front-end for passt(1) and pasta(1) forwarding configuration * * serialise.c - Serialisation of data structures over bytestreams * * Copyright Red Hat * Author: David Gibson */ #include #include #include #include #include #include #include "serialise.h" /** * seread_buf() - Fill a whole buffer from a file descriptor * @fd: File descriptor * @buf: Pointer to base of buffer * @len: Length of buffer * * Return: 0 on success, -1 on error (with errno set) * * #syscalls read */ int seread_buf(int fd, void *buf, size_t len) { size_t left = len; char *p = buf; while (left) { ssize_t rc; assert(left <= len); do rc = read(fd, p, left); while ((rc < 0) && errno == EINTR); if (rc < 0) return -1; if (rc == 0) { errno = ENODATA; return -1; } p += rc; left -= rc; } return 0; } /** * sewrite_buf() - write all of a buffer to an fd * @fd: File descriptor * @buf: Pointer to base of buffer * @len: Length of buffer * * Return: 0 on success, -1 on error (with errno set) * * #syscalls write */ int sewrite_buf(int fd, const void *buf, size_t len) { const char *p = buf; size_t left = len; while (left) { ssize_t rc; do rc = write(fd, p, left); while ((rc < 0) && errno == EINTR); if (rc < 0) return -1; p += rc; left -= rc; } return 0; } /** * seread_uXXX() - Receive a uXXX value from an fd * @fd: File descriptor to read from * @valp: Pointer to variable to update with read value * * Return: 0 on success, -1 on error */ /** * sewrite_uXXX() - Send a uXXX value to an fd * @fd: File descriptor to write to * @val: Value to send * * Return: 0 on success, -1 on error */ #define SERIALISE_UINT(bits) \ int seread_u##bits(int fd, uint##bits##_t *val) \ { \ uint##bits##_t beval; \ if (seread_var(fd, &beval) < 0) \ return -1; \ *val = be##bits##toh(beval); \ return 0; \ } \ int sewrite_u##bits(int fd, uint##bits##_t val) \ { \ uint##bits##_t beval = htobe##bits(val); \ return sewrite_var(fd, &beval); \ } #define be8toh(x) (x) #define htobe8(x) (x) SERIALISE_UINT(8) SERIALISE_UINT(32) #undef SERIALISE_UNIT /** * sewrite_str() - Write a string to an fd in length/value format * @fd: Socket to the client * @s: String to send * * Return: 0 on success, -1 on error */ int sewrite_str(int fd, const char *s) { uint32_t len = strlen(s) + 1; /* Include \0 */ if (sewrite_u32(fd, len) < 0) return -1; return sewrite_buf(fd, s, len); }