Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
folium-app
GitHub Repository: folium-app/Folium
Path: blob/a-new-beginning/SharedDependencies/Sources/libslirp/misc.c
2 views
1
/* SPDX-License-Identifier: BSD-3-Clause */
2
/*
3
* Copyright (c) 1995 Danny Gasparovski.
4
*/
5
6
#include "slirp.h"
7
#ifdef G_OS_UNIX
8
#include <sys/un.h>
9
#endif
10
11
void slirp_insque(void *a, void *b)
12
{
13
register struct slirp_quehead *element = (struct slirp_quehead *)a;
14
register struct slirp_quehead *head = (struct slirp_quehead *)b;
15
element->qh_link = head->qh_link;
16
head->qh_link = (struct slirp_quehead *)element;
17
element->qh_rlink = (struct slirp_quehead *)head;
18
((struct slirp_quehead *)(element->qh_link))->qh_rlink =
19
(struct slirp_quehead *)element;
20
}
21
22
void slirp_remque(void *a)
23
{
24
register struct slirp_quehead *element = (struct slirp_quehead *)a;
25
((struct slirp_quehead *)(element->qh_link))->qh_rlink = element->qh_rlink;
26
((struct slirp_quehead *)(element->qh_rlink))->qh_link = element->qh_link;
27
element->qh_rlink = NULL;
28
}
29
30
/* TODO: IPv6 */
31
struct gfwd_list *add_guestfwd(struct gfwd_list **ex_ptr, SlirpWriteCb write_cb,
32
void *opaque, struct in_addr addr, int port)
33
{
34
struct gfwd_list *f = g_new0(struct gfwd_list, 1);
35
36
f->write_cb = write_cb;
37
f->opaque = opaque;
38
f->ex_fport = port;
39
f->ex_addr = addr;
40
f->ex_next = *ex_ptr;
41
*ex_ptr = f;
42
43
return f;
44
}
45
46
struct gfwd_list *add_exec(struct gfwd_list **ex_ptr, const char *cmdline,
47
struct in_addr addr, int port)
48
{
49
struct gfwd_list *f = add_guestfwd(ex_ptr, NULL, NULL, addr, port);
50
51
f->ex_exec = g_strdup(cmdline);
52
53
return f;
54
}
55
56
struct gfwd_list *add_unix(struct gfwd_list **ex_ptr, const char *unixsock,
57
struct in_addr addr, int port)
58
{
59
struct gfwd_list *f = add_guestfwd(ex_ptr, NULL, NULL, addr, port);
60
61
f->ex_unix = g_strdup(unixsock);
62
63
return f;
64
}
65
66
int remove_guestfwd(struct gfwd_list **ex_ptr, struct in_addr addr, int port)
67
{
68
for (; *ex_ptr != NULL; ex_ptr = &((*ex_ptr)->ex_next)) {
69
struct gfwd_list *f = *ex_ptr;
70
if (f->ex_addr.s_addr == addr.s_addr && f->ex_fport == port) {
71
*ex_ptr = f->ex_next;
72
g_free(f->ex_exec);
73
g_free(f);
74
return 0;
75
}
76
}
77
return -1;
78
}
79
80
static int slirp_socketpair_with_oob(int sv[2])
81
{
82
struct sockaddr_in addr = {
83
.sin_family = AF_INET,
84
.sin_port = 0,
85
.sin_addr.s_addr = htonl(INADDR_LOOPBACK),
86
};
87
socklen_t addrlen = sizeof(addr);
88
int ret, s;
89
90
sv[1] = -1;
91
s = slirp_socket(AF_INET, SOCK_STREAM, 0);
92
if (s < 0 || bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||
93
listen(s, 1) < 0 ||
94
getsockname(s, (struct sockaddr *)&addr, &addrlen) < 0) {
95
goto err;
96
}
97
98
sv[1] = slirp_socket(AF_INET, SOCK_STREAM, 0);
99
if (sv[1] < 0) {
100
goto err;
101
}
102
/*
103
* This connect won't block because we've already listen()ed on
104
* the server end (even though we won't accept() the connection
105
* until later on).
106
*/
107
do {
108
ret = connect(sv[1], (struct sockaddr *)&addr, addrlen);
109
} while (ret < 0 && errno == EINTR);
110
if (ret < 0) {
111
goto err;
112
}
113
114
do {
115
sv[0] = accept(s, (struct sockaddr *)&addr, &addrlen);
116
} while (sv[0] < 0 && errno == EINTR);
117
if (sv[0] < 0) {
118
goto err;
119
}
120
121
closesocket(s);
122
return 0;
123
124
err:
125
g_critical("slirp_socketpair(): %s", strerror(errno));
126
if (s >= 0) {
127
closesocket(s);
128
}
129
if (sv[1] >= 0) {
130
closesocket(sv[1]);
131
}
132
return -1;
133
}
134
135
static void fork_exec_child_setup(gpointer data)
136
{
137
#ifndef _WIN32
138
setsid();
139
140
/* Unblock all signals and leave our exec()-ee to block what it wants */
141
sigset_t ss;
142
sigemptyset(&ss);
143
sigprocmask(SIG_SETMASK, &ss, NULL);
144
145
/* POSIX is obnoxious about SIGCHLD specifically across exec() */
146
signal(SIGCHLD, SIG_DFL);
147
#endif
148
}
149
150
#ifdef __GNUC__
151
#pragma GCC diagnostic push
152
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
153
#endif
154
155
#if !GLIB_CHECK_VERSION(2, 58, 0)
156
typedef struct SlirpGSpawnFds {
157
GSpawnChildSetupFunc child_setup;
158
gpointer user_data;
159
gint stdin_fd;
160
gint stdout_fd;
161
gint stderr_fd;
162
} SlirpGSpawnFds;
163
164
static inline void slirp_gspawn_fds_setup(gpointer user_data)
165
{
166
SlirpGSpawnFds *q = (SlirpGSpawnFds *)user_data;
167
168
dup2(q->stdin_fd, 0);
169
dup2(q->stdout_fd, 1);
170
dup2(q->stderr_fd, 2);
171
q->child_setup(q->user_data);
172
}
173
#endif
174
175
static inline gboolean
176
g_spawn_async_with_fds_slirp(const gchar *working_directory, gchar **argv,
177
gchar **envp, GSpawnFlags flags,
178
GSpawnChildSetupFunc child_setup,
179
gpointer user_data, GPid *child_pid, gint stdin_fd,
180
gint stdout_fd, gint stderr_fd, GError **error)
181
{
182
#if GLIB_CHECK_VERSION(2, 58, 0)
183
return g_spawn_async_with_fds(working_directory, argv, envp, flags,
184
child_setup, user_data, child_pid, stdin_fd,
185
stdout_fd, stderr_fd, error);
186
#else
187
SlirpGSpawnFds setup = {
188
.child_setup = child_setup,
189
.user_data = user_data,
190
.stdin_fd = stdin_fd,
191
.stdout_fd = stdout_fd,
192
.stderr_fd = stderr_fd,
193
};
194
195
return g_spawn_async(working_directory, argv, envp, flags,
196
slirp_gspawn_fds_setup, &setup, child_pid, error);
197
#endif
198
}
199
200
#define g_spawn_async_with_fds(wd, argv, env, f, c, d, p, ifd, ofd, efd, err) \
201
g_spawn_async_with_fds_slirp(wd, argv, env, f, c, d, p, ifd, ofd, efd, err)
202
203
#ifdef __GNUC__
204
#pragma GCC diagnostic pop
205
#endif
206
207
int fork_exec(struct socket *so, const char *ex)
208
{
209
GError *err = NULL;
210
gint argc = 0;
211
gchar **argv = NULL;
212
int opt, sp[2];
213
214
DEBUG_CALL("fork_exec");
215
DEBUG_ARG("so = %p", so);
216
DEBUG_ARG("ex = %p", ex);
217
218
if (slirp_socketpair_with_oob(sp) < 0) {
219
return 0;
220
}
221
222
if (!g_shell_parse_argv(ex, &argc, &argv, &err)) {
223
g_critical("fork_exec invalid command: %s\nerror: %s", ex, err->message);
224
g_error_free(err);
225
return 0;
226
}
227
228
g_spawn_async_with_fds(NULL /* cwd */, argv, NULL /* env */,
229
G_SPAWN_SEARCH_PATH, fork_exec_child_setup,
230
NULL /* data */, NULL /* child_pid */, sp[1], sp[1],
231
sp[1], &err);
232
g_strfreev(argv);
233
234
if (err) {
235
g_critical("fork_exec: %s", err->message);
236
g_error_free(err);
237
closesocket(sp[0]);
238
closesocket(sp[1]);
239
return 0;
240
}
241
242
so->s = sp[0];
243
closesocket(sp[1]);
244
slirp_socket_set_fast_reuse(so->s);
245
opt = 1;
246
setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE, &opt, sizeof(int));
247
slirp_set_nonblock(so->s);
248
so->slirp->cb->register_poll_fd(so->s, so->slirp->opaque);
249
return 1;
250
}
251
252
int open_unix(struct socket *so, const char *unixpath)
253
{
254
#ifdef G_OS_UNIX
255
struct sockaddr_un sa;
256
int s;
257
258
DEBUG_CALL("open_unix");
259
DEBUG_ARG("so = %p", so);
260
DEBUG_ARG("unixpath = %s", unixpath);
261
262
memset(&sa, 0, sizeof(sa));
263
sa.sun_family = AF_UNIX;
264
if (g_strlcpy(sa.sun_path, unixpath, sizeof(sa.sun_path)) >= sizeof(sa.sun_path)) {
265
g_critical("Bad unix path: %s", unixpath);
266
return 0;
267
}
268
269
s = slirp_socket(PF_UNIX, SOCK_STREAM, 0);
270
if (s < 0) {
271
g_critical("open_unix(): %s", strerror(errno));
272
return 0;
273
}
274
275
if (connect(s, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
276
g_critical("open_unix(): %s", strerror(errno));
277
closesocket(s);
278
return 0;
279
}
280
281
so->s = s;
282
slirp_set_nonblock(so->s);
283
so->slirp->cb->register_poll_fd(so->s, so->slirp->opaque);
284
285
return 1;
286
#else
287
g_assert_not_reached();
288
#endif
289
}
290
291
char *slirp_connection_info(Slirp *slirp)
292
{
293
GString *str = g_string_new(NULL);
294
const char *const tcpstates[] = {
295
[TCPS_CLOSED] = "CLOSED", [TCPS_LISTEN] = "LISTEN",
296
[TCPS_SYN_SENT] = "SYN_SENT", [TCPS_SYN_RECEIVED] = "SYN_RCVD",
297
[TCPS_ESTABLISHED] = "ESTABLISHED", [TCPS_CLOSE_WAIT] = "CLOSE_WAIT",
298
[TCPS_FIN_WAIT_1] = "FIN_WAIT_1", [TCPS_CLOSING] = "CLOSING",
299
[TCPS_LAST_ACK] = "LAST_ACK", [TCPS_FIN_WAIT_2] = "FIN_WAIT_2",
300
[TCPS_TIME_WAIT] = "TIME_WAIT",
301
};
302
struct in_addr dst_addr;
303
struct sockaddr_in src;
304
socklen_t src_len;
305
uint16_t dst_port;
306
struct socket *so;
307
const char *state;
308
char addr[INET_ADDRSTRLEN];
309
char buf[20];
310
311
g_string_append_printf(str,
312
" Protocol[State] FD Source Address Port "
313
"Dest. Address Port RecvQ SendQ\n");
314
315
/* TODO: IPv6 */
316
317
for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so->so_next) {
318
if (so->so_state & SS_HOSTFWD) {
319
state = "HOST_FORWARD";
320
} else if (so->so_tcpcb) {
321
state = tcpstates[so->so_tcpcb->t_state];
322
} else {
323
state = "NONE";
324
}
325
if (so->so_state & (SS_HOSTFWD | SS_INCOMING)) {
326
src_len = sizeof(src);
327
getsockname(so->s, (struct sockaddr *)&src, &src_len);
328
dst_addr = so->so_laddr;
329
dst_port = so->so_lport;
330
} else {
331
src.sin_addr = so->so_laddr;
332
src.sin_port = so->so_lport;
333
dst_addr = so->so_faddr;
334
dst_port = so->so_fport;
335
}
336
slirp_fmt0(buf, sizeof(buf), " TCP[%s]", state);
337
g_string_append_printf(str, "%-19s %3d %15s %5d ", buf, so->s,
338
src.sin_addr.s_addr ?
339
inet_ntop(AF_INET, &src.sin_addr, addr, sizeof(addr)) : "*",
340
ntohs(src.sin_port));
341
g_string_append_printf(str, "%15s %5d %5d %5d\n",
342
inet_ntop(AF_INET, &dst_addr, addr, sizeof(addr)),
343
ntohs(dst_port), so->so_rcv.sb_cc,
344
so->so_snd.sb_cc);
345
}
346
347
for (so = slirp->udb.so_next; so != &slirp->udb; so = so->so_next) {
348
if (so->so_state & SS_HOSTFWD) {
349
slirp_fmt0(buf, sizeof(buf), " UDP[HOST_FORWARD]");
350
src_len = sizeof(src);
351
getsockname(so->s, (struct sockaddr *)&src, &src_len);
352
dst_addr = so->so_laddr;
353
dst_port = so->so_lport;
354
} else {
355
slirp_fmt0(buf, sizeof(buf), " UDP[%d sec]",
356
(so->so_expire - curtime) / 1000);
357
src.sin_addr = so->so_laddr;
358
src.sin_port = so->so_lport;
359
dst_addr = so->so_faddr;
360
dst_port = so->so_fport;
361
}
362
g_string_append_printf(str, "%-19s %3d %15s %5d ", buf, so->s,
363
src.sin_addr.s_addr ?
364
inet_ntop(AF_INET, &src.sin_addr, addr, sizeof(addr)) : "*",
365
ntohs(src.sin_port));
366
g_string_append_printf(str, "%15s %5d %5d %5d\n",
367
inet_ntop(AF_INET, &dst_addr, addr, sizeof(addr)),
368
ntohs(dst_port), so->so_rcv.sb_cc,
369
so->so_snd.sb_cc);
370
}
371
372
for (so = slirp->icmp.so_next; so != &slirp->icmp; so = so->so_next) {
373
slirp_fmt0(buf, sizeof(buf), " ICMP[%d sec]",
374
(so->so_expire - curtime) / 1000);
375
src.sin_addr = so->so_laddr;
376
dst_addr = so->so_faddr;
377
g_string_append_printf(str, "%-19s %3d %15s - ", buf, so->s,
378
src.sin_addr.s_addr ?
379
inet_ntop(AF_INET, &src.sin_addr, addr, sizeof(addr)) : "*");
380
g_string_append_printf(str, "%15s - %5d %5d\n",
381
inet_ntop(AF_INET, &dst_addr, addr, sizeof(addr)),
382
so->so_rcv.sb_cc, so->so_snd.sb_cc);
383
}
384
385
return g_string_free(str, FALSE);
386
}
387
388
char *slirp_neighbor_info(Slirp *slirp)
389
{
390
GString *str = g_string_new(NULL);
391
ArpTable *arp_table = &slirp->arp_table;
392
NdpTable *ndp_table = &slirp->ndp_table;
393
char ip_addr[INET6_ADDRSTRLEN];
394
char eth_addr[ETH_ADDRSTRLEN];
395
const char *ip;
396
397
g_string_append_printf(str, " %5s %-17s %s\n",
398
"Table", "MacAddr", "IP Address");
399
400
for (int i = 0; i < ARP_TABLE_SIZE; ++i) {
401
struct in_addr addr;
402
addr.s_addr = arp_table->table[i].ar_sip;
403
if (!addr.s_addr) {
404
continue;
405
}
406
ip = inet_ntop(AF_INET, &addr, ip_addr, sizeof(ip_addr));
407
g_assert(ip != NULL);
408
g_string_append_printf(str, " %5s %-17s %s\n", "ARP",
409
slirp_ether_ntoa(arp_table->table[i].ar_sha,
410
eth_addr, sizeof(eth_addr)),
411
ip);
412
}
413
414
for (int i = 0; i < NDP_TABLE_SIZE; ++i) {
415
if (in6_zero(&ndp_table->table[i].ip_addr)) {
416
continue;
417
}
418
ip = inet_ntop(AF_INET6, &ndp_table->table[i].ip_addr, ip_addr,
419
sizeof(ip_addr));
420
g_assert(ip != NULL);
421
g_string_append_printf(str, " %5s %-17s %s\n", "NDP",
422
slirp_ether_ntoa(ndp_table->table[i].eth_addr,
423
eth_addr, sizeof(eth_addr)),
424
ip);
425
}
426
427
return g_string_free(str, FALSE);
428
}
429
430
int slirp_bind_outbound(struct socket *so, unsigned short af)
431
{
432
int ret = 0;
433
struct sockaddr *addr = NULL;
434
int addr_size = 0;
435
436
if (af == AF_INET && so->slirp->outbound_addr != NULL) {
437
addr = (struct sockaddr *)so->slirp->outbound_addr;
438
addr_size = sizeof(struct sockaddr_in);
439
} else if (af == AF_INET6 && so->slirp->outbound_addr6 != NULL) {
440
addr = (struct sockaddr *)so->slirp->outbound_addr6;
441
addr_size = sizeof(struct sockaddr_in6);
442
}
443
444
if (addr != NULL) {
445
ret = bind(so->s, addr, addr_size);
446
}
447
return ret;
448
}
449
450