// SPDX-License-Identifier: GPL-2.0-or-later /* PESTO - Programmable Extensible Socket Translation Orchestrator * front-end for passt(1) and pasta(1) forwarding configuration * * pesto.c - Main program (it's not actually extensible) * * Copyright (c) 2026 Red Hat GmbH * Author: Stefano Brivio */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "seccomp_pesto.h" #include "linux_dep.h" #include "epoll_type.h" #include "util.h" #include "passt.h" #include "fwd.h" #include "conf.h" /** * main() - Entry point and whole program with loop * @argc: Argument count * @argv: Arguments: socket path, operation, port specifiers * * Return: 0 on success, won't return on failure * * #syscalls:pesto connect write close exit_group * #syscalls:pesto socket s390x:socketcall i686:socketcall * #syscalls:pesto recvfrom recvmsg arm:recv ppc64le:recv * #syscalls:pesto sendto sendmsg arm:send ppc64le:send */ int main(int argc, char **argv) { struct sockaddr_un a = { AF_UNIX, "" }; struct conf_op conf_ops[128]; int count = 0, ret, i, s; struct sock_fprog prog; prctl(PR_SET_DUMPABLE, 0); prog.len = (unsigned short)sizeof(filter_pesto) / sizeof(filter_pesto[0]); prog.filter = filter_pesto; if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) || prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) { fprintf(stderr, "Failed to apply seccomp filter\n"); _exit(1); } if (argc < 4) { fprintf(stderr, "Usage: %s PATH add|del SPEC [auto] [weak] \\" "[add|del SPEC [auto] [weak]] ...\n", argv[0]); _exit(2); } if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { fprintf(stderr, "Failed to create AF_UNIX socket: %i\n", errno); _exit(1); } ret = snprintf(a.sun_path, sizeof(a.sun_path), "%s", argv[1]); if (ret <= 0 || ret >= (int)sizeof(a.sun_path)) { fprintf(stderr, "Invalid socket path\n"); _exit(2); } while (connect(s, (struct sockaddr *)&a, sizeof(a))) { if (errno == ECONNREFUSED) continue; fprintf(stderr, "Failed to connect to %s: %s\n", a.sun_path, strerror_(errno)); _exit(1); } for (i = 2; i + 2 <= argc; ) { struct fwd_rule *r = &conf_ops[count].r; if (!strcmp(argv[i], "add")) conf_ops[count].op = RULE_ADD; else if (!strcmp(argv[i], "del")) conf_ops[count].op = RULE_DEL; else _exit(1); i++; /* TODO: Factor relevant part out of conf_ports() and reuse */ r->to = r->last = r->first = atoi(argv[i]); i++; if (i < argc && !strcmp(argv[i], "auto")) { r->flags |= FWD_SCAN; i++; } if (i < argc && !strcmp(argv[i], "weak")) { r->flags |= FWD_WEAK; i++; } fprintf(stderr, "Read rule for ports %i-%i:%i\n", r->first, r->last, r->to); count++; } send(s, conf_ops, sizeof(conf_ops[0]) * count, 0); return 0; }