1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
| | // 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 <sbrivio@redhat.com>
*/
#include <arpa/inet.h>
#include <sys/prctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <unistd.h>
#include <linux/audit.h>
#include <linux/capability.h>
#include <linux/filter.h>
#include <linux/seccomp.h>
#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;
}
|