Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
folium-app
GitHub Repository: folium-app/Folium
Path: blob/a-new-beginning/SharedDependencies/Sources/libslirp/slirp.c
2 views
1
/* SPDX-License-Identifier: MIT */
2
/*
3
* libslirp glue
4
*
5
* Copyright (c) 2004-2008 Fabrice Bellard
6
*
7
* Permission is hereby granted, free of charge, to any person obtaining a copy
8
* of this software and associated documentation files (the "Software"), to deal
9
* in the Software without restriction, including without limitation the rights
10
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
* copies of the Software, and to permit persons to whom the Software is
12
* furnished to do so, subject to the following conditions:
13
*
14
* The above copyright notice and this permission notice shall be included in
15
* all copies or substantial portions of the Software.
16
*
17
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
* THE SOFTWARE.
24
*/
25
#include "slirp.h"
26
27
28
#ifndef _WIN32
29
#include <net/if.h>
30
#endif
31
32
/* https://gitlab.freedesktop.org/slirp/libslirp/issues/18 */
33
#if defined(__NetBSD__) && defined(if_mtu)
34
#undef if_mtu
35
#endif
36
37
#if defined(_WIN32)
38
39
#define INITIAL_DNS_ADDR_BUF_SIZE 32 * 1024
40
#define REALLOC_RETRIES 5
41
42
// Broadcast site local DNS resolvers. We do not use these because they are
43
// highly unlikely to be valid.
44
// https://www.ietf.org/proceedings/52/I-D/draft-ietf-ipngwg-dns-discovery-03.txt
45
static const struct in6_addr SITE_LOCAL_DNS_BROADCAST_ADDRS[] = {
46
{
47
{{
48
0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
49
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
50
}}
51
},
52
{
53
{{
54
0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
55
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02
56
}}
57
},
58
{
59
{{
60
0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
61
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
62
}}
63
},
64
};
65
66
#endif
67
68
int slirp_debug;
69
70
/* Define to 1 if you want KEEPALIVE timers */
71
bool slirp_do_keepalive;
72
73
/* host loopback address */
74
struct in_addr loopback_addr;
75
/* host loopback network mask */
76
unsigned long loopback_mask;
77
78
/* emulated hosts use the MAC addr 52:55:IP:IP:IP:IP */
79
static const uint8_t special_ethaddr[ETH_ALEN] = { 0x52, 0x55, 0x00,
80
0x00, 0x00, 0x00 };
81
82
unsigned curtime;
83
84
static struct in_addr dns_addr;
85
static struct in6_addr dns6_addr;
86
static uint32_t dns6_scope_id;
87
static unsigned dns_addr_time;
88
static unsigned dns6_addr_time;
89
90
#define TIMEOUT_FAST 2 /* milliseconds */
91
#define TIMEOUT_SLOW 499 /* milliseconds */
92
/* for the aging of certain requests like DNS */
93
#define TIMEOUT_DEFAULT 1000 /* milliseconds */
94
95
#if defined(_WIN32)
96
97
int get_dns_addr(struct in_addr *pdns_addr)
98
{
99
FIXED_INFO *FixedInfo = NULL;
100
ULONG BufLen;
101
DWORD ret;
102
IP_ADDR_STRING *pIPAddr;
103
struct in_addr tmp_addr;
104
105
if (dns_addr.s_addr != 0 && (curtime - dns_addr_time) < TIMEOUT_DEFAULT) {
106
*pdns_addr = dns_addr;
107
return 0;
108
}
109
110
FixedInfo = (FIXED_INFO *)GlobalAlloc(GPTR, sizeof(FIXED_INFO));
111
BufLen = sizeof(FIXED_INFO);
112
113
if (ERROR_BUFFER_OVERFLOW == GetNetworkParams(FixedInfo, &BufLen)) {
114
if (FixedInfo) {
115
GlobalFree(FixedInfo);
116
FixedInfo = NULL;
117
}
118
FixedInfo = GlobalAlloc(GPTR, BufLen);
119
}
120
121
if ((ret = GetNetworkParams(FixedInfo, &BufLen)) != ERROR_SUCCESS) {
122
printf("GetNetworkParams failed. ret = %08x\n", (unsigned)ret);
123
if (FixedInfo) {
124
GlobalFree(FixedInfo);
125
FixedInfo = NULL;
126
}
127
return -1;
128
}
129
130
pIPAddr = &(FixedInfo->DnsServerList);
131
inet_aton(pIPAddr->IpAddress.String, &tmp_addr);
132
*pdns_addr = tmp_addr;
133
dns_addr = tmp_addr;
134
dns_addr_time = curtime;
135
if (FixedInfo) {
136
GlobalFree(FixedInfo);
137
FixedInfo = NULL;
138
}
139
return 0;
140
}
141
142
static int is_site_local_dns_broadcast(struct in6_addr *address)
143
{
144
int i;
145
for (i = 0; i < G_N_ELEMENTS(SITE_LOCAL_DNS_BROADCAST_ADDRS); i++) {
146
if (in6_equal(address, &SITE_LOCAL_DNS_BROADCAST_ADDRS[i])) {
147
return 1;
148
}
149
}
150
return 0;
151
}
152
153
static void print_dns_v6_address(struct in6_addr address)
154
{
155
char address_str[INET6_ADDRSTRLEN] = "";
156
if (inet_ntop(AF_INET6, &address, address_str, INET6_ADDRSTRLEN)
157
== NULL) {
158
DEBUG_ERROR("Failed to stringify IPv6 address for logging.");
159
return;
160
}
161
DEBUG_RAW_CALL("IPv6 DNS server found: %s", address_str);
162
}
163
164
// Gets the first valid DNS resolver with an IPv6 address.
165
// Ignores any site local broadcast DNS servers, as these
166
// are on deprecated addresses and not generally expected
167
// to work. Further details at:
168
// https://www.ietf.org/proceedings/52/I-D/draft-ietf-ipngwg-dns-discovery-03.txt
169
static int get_ipv6_dns_server(struct in6_addr *dns_server_address, uint32_t *scope_id)
170
{
171
PIP_ADAPTER_ADDRESSES addresses = NULL;
172
PIP_ADAPTER_ADDRESSES address = NULL;
173
IP_ADAPTER_DNS_SERVER_ADDRESS *dns_server = NULL;
174
struct sockaddr_in6 *dns_v6_addr = NULL;
175
176
ULONG buf_size = INITIAL_DNS_ADDR_BUF_SIZE;
177
DWORD res = ERROR_BUFFER_OVERFLOW;
178
int i;
179
180
for (i = 0; i < REALLOC_RETRIES; i++) {
181
// If non null, we hit buffer overflow, free it so we can try again.
182
if (addresses != NULL) {
183
g_free(addresses);
184
}
185
186
addresses = g_malloc(buf_size);
187
res = GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL,
188
addresses, &buf_size);
189
190
if (res != ERROR_BUFFER_OVERFLOW) {
191
break;
192
}
193
}
194
195
if (res != NO_ERROR) {
196
DEBUG_ERROR("Failed to get IPv6 DNS addresses due to error %lX", res);
197
goto failure;
198
}
199
200
address = addresses;
201
for (address = addresses; address != NULL; address = address->Next) {
202
for (dns_server = address->FirstDnsServerAddress;
203
dns_server != NULL;
204
dns_server = dns_server->Next) {
205
206
if (dns_server->Address.lpSockaddr->sa_family != AF_INET6) {
207
continue;
208
}
209
210
dns_v6_addr = (struct sockaddr_in6 *)dns_server->Address.lpSockaddr;
211
if (is_site_local_dns_broadcast(&dns_v6_addr->sin6_addr) == 0) {
212
print_dns_v6_address(dns_v6_addr->sin6_addr);
213
*dns_server_address = dns_v6_addr->sin6_addr;
214
*scope_id = dns_v6_addr->sin6_scope_id;
215
216
g_free(addresses);
217
return 0;
218
}
219
}
220
}
221
222
DEBUG_ERROR("No IPv6 DNS servers found.\n");
223
224
failure:
225
g_free(addresses);
226
return -1;
227
}
228
229
int get_dns6_addr(struct in6_addr *pdns6_addr, uint32_t *scope_id)
230
{
231
if (!in6_zero(&dns6_addr) && (curtime - dns6_addr_time) < TIMEOUT_DEFAULT) {
232
*pdns6_addr = dns6_addr;
233
*scope_id = dns6_scope_id;
234
return 0;
235
}
236
237
if (get_ipv6_dns_server(pdns6_addr, scope_id) == 0) {
238
dns6_addr = *pdns6_addr;
239
dns6_addr_time = curtime;
240
dns6_scope_id = *scope_id;
241
return 0;
242
}
243
244
return -1;
245
}
246
247
static void winsock_cleanup(void)
248
{
249
WSACleanup();
250
}
251
252
#elif defined(__APPLE__)
253
254
#include <resolv.h>
255
256
static int get_dns_addr_cached(void *pdns_addr, void *cached_addr,
257
socklen_t addrlen, unsigned *cached_time)
258
{
259
if (curtime - *cached_time < TIMEOUT_DEFAULT) {
260
memcpy(pdns_addr, cached_addr, addrlen);
261
return 0;
262
}
263
return 1;
264
}
265
266
static int get_dns_addr_libresolv(int af, void *pdns_addr, void *cached_addr,
267
socklen_t addrlen,
268
uint32_t *scope_id, uint32_t *cached_scope_id,
269
unsigned *cached_time)
270
{
271
struct __res_state state;
272
union res_sockaddr_union servers[NI_MAXSERV];
273
int count;
274
int found;
275
void *addr;
276
277
// we only support IPv4 and IPv4, we assume it's one or the other
278
assert(af == AF_INET || af == AF_INET6);
279
280
if (res_ninit(&state) != 0) {
281
return -1;
282
}
283
284
count = res_getservers(&state, servers, NI_MAXSERV);
285
found = 0;
286
DEBUG_MISC("IP address of your DNS(s):");
287
for (int i = 0; i < count; i++) {
288
if (af == servers[i].sin.sin_family) {
289
found++;
290
}
291
if (af == AF_INET) {
292
addr = &servers[i].sin.sin_addr;
293
} else { // af == AF_INET6
294
addr = &servers[i].sin6.sin6_addr;
295
}
296
297
// we use the first found entry
298
if (found == 1) {
299
memcpy(pdns_addr, addr, addrlen);
300
memcpy(cached_addr, addr, addrlen);
301
if (scope_id) {
302
*scope_id = 0;
303
}
304
if (cached_scope_id) {
305
*cached_scope_id = 0;
306
}
307
*cached_time = curtime;
308
}
309
310
if (found > 3) {
311
DEBUG_MISC(" (more)");
312
break;
313
} else if (slirp_debug & DBG_MISC) {
314
char s[INET6_ADDRSTRLEN];
315
const char *res = inet_ntop(af, addr, s, sizeof(s));
316
if (!res) {
317
res = " (string conversion error)";
318
}
319
DEBUG_MISC(" %s", res);
320
}
321
}
322
323
res_ndestroy(&state);
324
if (!found)
325
return -1;
326
return 0;
327
}
328
329
int get_dns_addr(struct in_addr *pdns_addr)
330
{
331
if (dns_addr.s_addr != 0) {
332
int ret;
333
ret = get_dns_addr_cached(pdns_addr, &dns_addr, sizeof(dns_addr),
334
&dns_addr_time);
335
if (ret <= 0) {
336
return ret;
337
}
338
}
339
return get_dns_addr_libresolv(AF_INET, pdns_addr, &dns_addr,
340
sizeof(dns_addr), NULL, NULL, &dns_addr_time);
341
}
342
343
int get_dns6_addr(struct in6_addr *pdns6_addr, uint32_t *scope_id)
344
{
345
if (!in6_zero(&dns6_addr)) {
346
int ret;
347
ret = get_dns_addr_cached(pdns6_addr, &dns6_addr, sizeof(dns6_addr),
348
&dns6_addr_time);
349
if (ret == 0) {
350
*scope_id = dns6_scope_id;
351
}
352
if (ret <= 0) {
353
return ret;
354
}
355
}
356
return get_dns_addr_libresolv(AF_INET6, pdns6_addr, &dns6_addr,
357
sizeof(dns6_addr),
358
scope_id, &dns6_scope_id, &dns6_addr_time);
359
}
360
361
#else // !defined(_WIN32) && !defined(__APPLE__)
362
363
#if defined(__HAIKU__)
364
#define RESOLV_CONF_PATH "/boot/system/settings/network/resolv.conf"
365
#else
366
#define RESOLV_CONF_PATH "/etc/resolv.conf"
367
#endif
368
369
static int get_dns_addr_cached(void *pdns_addr, void *cached_addr,
370
socklen_t addrlen, struct stat *cached_stat,
371
unsigned *cached_time)
372
{
373
struct stat old_stat;
374
if (curtime - *cached_time < TIMEOUT_DEFAULT) {
375
memcpy(pdns_addr, cached_addr, addrlen);
376
return 0;
377
}
378
old_stat = *cached_stat;
379
if (stat(RESOLV_CONF_PATH, cached_stat) != 0) {
380
return -1;
381
}
382
if (cached_stat->st_dev == old_stat.st_dev &&
383
cached_stat->st_ino == old_stat.st_ino &&
384
cached_stat->st_size == old_stat.st_size &&
385
cached_stat->st_mtime == old_stat.st_mtime) {
386
memcpy(pdns_addr, cached_addr, addrlen);
387
return 0;
388
}
389
return 1;
390
}
391
392
static bool try_and_setdns_server(int af, unsigned found, unsigned if_index,
393
const char *buff2, void *pdns_addr, void *cached_addr,
394
socklen_t addrlen, uint32_t *scope_id, uint32_t *cached_scope_id,
395
unsigned *cached_time)
396
{
397
union {
398
struct in_addr dns_addr;
399
struct in6_addr dns6_addr;
400
} tmp_addr;
401
402
assert(sizeof(tmp_addr) >= addrlen);
403
404
if (!inet_pton(af, buff2, &tmp_addr))
405
return false;
406
407
/* If it's the first one, set it to dns_addr */
408
if (!found) {
409
memcpy(pdns_addr, &tmp_addr, addrlen);
410
memcpy(cached_addr, &tmp_addr, addrlen);
411
if (scope_id) {
412
*scope_id = if_index;
413
}
414
if (cached_scope_id) {
415
*cached_scope_id = if_index;
416
}
417
*cached_time = curtime;
418
}
419
420
if (found > 2) {
421
DEBUG_MISC(" (more)");
422
} else if (slirp_debug & DBG_MISC) {
423
char s[INET6_ADDRSTRLEN];
424
const char *res = inet_ntop(af, &tmp_addr, s, sizeof(s));
425
if (!res) {
426
res = " (string conversion error)";
427
}
428
DEBUG_MISC(" %s", res);
429
}
430
431
return true;
432
}
433
434
static int get_dns_addr_resolv_conf(int af, void *pdns_addr, void *cached_addr,
435
socklen_t addrlen,
436
uint32_t *scope_id, uint32_t *cached_scope_id,
437
unsigned *cached_time)
438
{
439
char buff[512];
440
char buff2[257];
441
FILE *f;
442
int found = 0;
443
unsigned if_index;
444
unsigned nameservers = 0;
445
446
f = fopen(RESOLV_CONF_PATH, "r");
447
if (!f)
448
return -1;
449
450
DEBUG_MISC("IP address of your DNS(s):");
451
while (fgets(buff, 512, f) != NULL) {
452
if (sscanf(buff, "nameserver%*[ \t]%256s", buff2) == 1) {
453
char *c = strchr(buff2, '%');
454
if (c) {
455
if_index = if_nametoindex(c + 1);
456
*c = '\0';
457
} else {
458
if_index = 0;
459
}
460
461
nameservers++;
462
463
if (!try_and_setdns_server(af, found, if_index, buff2, pdns_addr,
464
cached_addr, addrlen, scope_id,
465
cached_scope_id, cached_time))
466
continue;
467
468
if (++found > 3)
469
break;
470
}
471
}
472
fclose(f);
473
if (nameservers && !found)
474
return -1;
475
if (!nameservers) {
476
found += try_and_setdns_server(af, found, 0, "127.0.0.1",
477
pdns_addr, cached_addr, addrlen, scope_id,
478
cached_scope_id, cached_time);
479
found += try_and_setdns_server(af, found, 0, "::1",
480
pdns_addr, cached_addr, addrlen, scope_id,
481
cached_scope_id, cached_time);
482
}
483
484
return found ? 0 : -1;
485
}
486
487
int get_dns_addr(struct in_addr *pdns_addr)
488
{
489
static struct stat dns_addr_stat;
490
491
if (dns_addr.s_addr != 0) {
492
int ret;
493
ret = get_dns_addr_cached(pdns_addr, &dns_addr, sizeof(dns_addr),
494
&dns_addr_stat, &dns_addr_time);
495
if (ret <= 0) {
496
return ret;
497
}
498
}
499
return get_dns_addr_resolv_conf(AF_INET, pdns_addr, &dns_addr,
500
sizeof(dns_addr),
501
NULL, NULL, &dns_addr_time);
502
}
503
504
int get_dns6_addr(struct in6_addr *pdns6_addr, uint32_t *scope_id)
505
{
506
static struct stat dns6_addr_stat;
507
508
if (!in6_zero(&dns6_addr)) {
509
int ret;
510
ret = get_dns_addr_cached(pdns6_addr, &dns6_addr, sizeof(dns6_addr),
511
&dns6_addr_stat, &dns6_addr_time);
512
if (ret == 0) {
513
*scope_id = dns6_scope_id;
514
}
515
if (ret <= 0) {
516
return ret;
517
}
518
}
519
return get_dns_addr_resolv_conf(AF_INET6, pdns6_addr, &dns6_addr,
520
sizeof(dns6_addr),
521
scope_id, &dns6_scope_id, &dns6_addr_time);
522
}
523
524
#endif
525
526
static void slirp_init_once(void)
527
{
528
static int initialized;
529
const char *debug;
530
#ifdef _WIN32
531
WSADATA Data;
532
#endif
533
534
if (initialized) {
535
return;
536
}
537
initialized = 1;
538
539
#ifdef _WIN32
540
WSAStartup(MAKEWORD(2, 0), &Data);
541
atexit(winsock_cleanup);
542
#endif
543
544
loopback_addr.s_addr = htonl(INADDR_LOOPBACK);
545
loopback_mask = htonl(IN_CLASSA_NET);
546
547
debug = g_getenv("SLIRP_DEBUG");
548
if (debug) {
549
const GDebugKey keys[] = {
550
{ "call", DBG_CALL },
551
{ "misc", DBG_MISC },
552
{ "error", DBG_ERROR },
553
{ "tftp", DBG_TFTP },
554
{ "verbose_call", DBG_VERBOSE_CALL },
555
};
556
slirp_debug = g_parse_debug_string(debug, keys, G_N_ELEMENTS(keys));
557
}
558
}
559
560
static void ra_timer_handler_cb(void *opaque)
561
{
562
Slirp *slirp = opaque;
563
564
ra_timer_handler(slirp, NULL);
565
}
566
567
void slirp_handle_timer(Slirp *slirp, SlirpTimerId id, void *cb_opaque)
568
{
569
g_return_if_fail(id >= 0 && id < SLIRP_TIMER_NUM);
570
571
switch (id) {
572
case SLIRP_TIMER_RA:
573
ra_timer_handler(slirp, cb_opaque);
574
return;
575
default:
576
abort();
577
}
578
}
579
580
void *slirp_timer_new(Slirp *slirp, SlirpTimerId id, void *cb_opaque)
581
{
582
g_return_val_if_fail(id >= 0 && id < SLIRP_TIMER_NUM, NULL);
583
584
if (slirp->cfg_version >= 4 && slirp->cb->timer_new_opaque) {
585
return slirp->cb->timer_new_opaque(id, cb_opaque, slirp->opaque);
586
}
587
588
switch (id) {
589
case SLIRP_TIMER_RA:
590
g_return_val_if_fail(cb_opaque == NULL, NULL);
591
return slirp->cb->timer_new(ra_timer_handler_cb, slirp, slirp->opaque);
592
593
default:
594
abort();
595
}
596
}
597
598
Slirp *slirp_new(const SlirpConfig *cfg, const SlirpCb *callbacks, void *opaque)
599
{
600
Slirp *slirp;
601
602
g_return_val_if_fail(cfg != NULL, NULL);
603
g_return_val_if_fail(cfg->version >= SLIRP_CONFIG_VERSION_MIN, NULL);
604
g_return_val_if_fail(cfg->version <= SLIRP_CONFIG_VERSION_MAX, NULL);
605
g_return_val_if_fail(cfg->if_mtu >= IF_MTU_MIN || cfg->if_mtu == 0, NULL);
606
g_return_val_if_fail(cfg->if_mtu <= IF_MTU_MAX, NULL);
607
g_return_val_if_fail(cfg->if_mru >= IF_MRU_MIN || cfg->if_mru == 0, NULL);
608
g_return_val_if_fail(cfg->if_mru <= IF_MRU_MAX, NULL);
609
g_return_val_if_fail(!cfg->bootfile ||
610
(strlen(cfg->bootfile) <
611
G_SIZEOF_MEMBER(struct bootp_t, bp_file)), NULL);
612
613
slirp = g_malloc0(sizeof(Slirp));
614
615
slirp_init_once();
616
617
slirp->cfg_version = cfg->version;
618
slirp->opaque = opaque;
619
slirp->cb = callbacks;
620
slirp->grand = g_rand_new();
621
slirp->restricted = cfg->restricted;
622
623
slirp->in_enabled = cfg->in_enabled;
624
slirp->in6_enabled = cfg->in6_enabled;
625
626
if_init(slirp);
627
ip_init(slirp);
628
629
m_init(slirp);
630
631
slirp->vnetwork_addr = cfg->vnetwork;
632
slirp->vnetwork_mask = cfg->vnetmask;
633
slirp->vhost_addr = cfg->vhost;
634
slirp->vprefix_addr6 = cfg->vprefix_addr6;
635
slirp->vprefix_len = cfg->vprefix_len;
636
slirp->vhost_addr6 = cfg->vhost6;
637
if (cfg->vhostname) {
638
slirp_pstrcpy(slirp->client_hostname, sizeof(slirp->client_hostname),
639
cfg->vhostname);
640
}
641
slirp->tftp_prefix = g_strdup(cfg->tftp_path);
642
slirp->bootp_filename = g_strdup(cfg->bootfile);
643
slirp->vdomainname = g_strdup(cfg->vdomainname);
644
slirp->vdhcp_startaddr = cfg->vdhcp_start;
645
slirp->vnameserver_addr = cfg->vnameserver;
646
slirp->vnameserver_addr6 = cfg->vnameserver6;
647
slirp->tftp_server_name = g_strdup(cfg->tftp_server_name);
648
649
if (cfg->vdnssearch) {
650
translate_dnssearch(slirp, cfg->vdnssearch);
651
}
652
slirp->if_mtu = cfg->if_mtu == 0 ? IF_MTU_DEFAULT : cfg->if_mtu;
653
slirp->if_mru = cfg->if_mru == 0 ? IF_MRU_DEFAULT : cfg->if_mru;
654
slirp->disable_host_loopback = cfg->disable_host_loopback;
655
slirp->enable_emu = cfg->enable_emu;
656
657
if (cfg->version >= 2) {
658
slirp->outbound_addr = cfg->outbound_addr;
659
slirp->outbound_addr6 = cfg->outbound_addr6;
660
} else {
661
slirp->outbound_addr = NULL;
662
slirp->outbound_addr6 = NULL;
663
}
664
665
if (cfg->version >= 3) {
666
slirp->disable_dns = cfg->disable_dns;
667
} else {
668
slirp->disable_dns = false;
669
}
670
671
if (cfg->version >= 4) {
672
slirp->disable_dhcp = cfg->disable_dhcp;
673
} else {
674
slirp->disable_dhcp = false;
675
}
676
677
if (slirp->cfg_version >= 4 && slirp->cb->init_completed) {
678
slirp->cb->init_completed(slirp, slirp->opaque);
679
}
680
681
if (cfg->version >= 5) {
682
slirp->mfr_id = cfg->mfr_id;
683
memcpy(slirp->oob_eth_addr, cfg->oob_eth_addr, ETH_ALEN);
684
} else {
685
slirp->mfr_id = 0;
686
memset(slirp->oob_eth_addr, 0, ETH_ALEN);
687
}
688
689
ip6_post_init(slirp);
690
return slirp;
691
}
692
693
Slirp *slirp_init(int restricted, bool in_enabled, struct in_addr vnetwork,
694
struct in_addr vnetmask, struct in_addr vhost,
695
bool in6_enabled, struct in6_addr vprefix_addr6,
696
uint8_t vprefix_len, struct in6_addr vhost6,
697
const char *vhostname, const char *tftp_server_name,
698
const char *tftp_path, const char *bootfile,
699
struct in_addr vdhcp_start, struct in_addr vnameserver,
700
struct in6_addr vnameserver6, const char **vdnssearch,
701
const char *vdomainname, const SlirpCb *callbacks,
702
void *opaque)
703
{
704
SlirpConfig cfg;
705
memset(&cfg, 0, sizeof(cfg));
706
cfg.version = 1;
707
cfg.restricted = restricted;
708
cfg.in_enabled = in_enabled;
709
cfg.vnetwork = vnetwork;
710
cfg.vnetmask = vnetmask;
711
cfg.vhost = vhost;
712
cfg.in6_enabled = in6_enabled;
713
cfg.vprefix_addr6 = vprefix_addr6;
714
cfg.vprefix_len = vprefix_len;
715
cfg.vhost6 = vhost6;
716
cfg.vhostname = vhostname;
717
cfg.tftp_server_name = tftp_server_name;
718
cfg.tftp_path = tftp_path;
719
cfg.bootfile = bootfile;
720
cfg.vdhcp_start = vdhcp_start;
721
cfg.vnameserver = vnameserver;
722
cfg.vnameserver6 = vnameserver6;
723
cfg.vdnssearch = vdnssearch;
724
cfg.vdomainname = vdomainname;
725
return slirp_new(&cfg, callbacks, opaque);
726
}
727
728
void slirp_cleanup(Slirp *slirp)
729
{
730
struct gfwd_list *e, *next;
731
732
for (e = slirp->guestfwd_list; e; e = next) {
733
next = e->ex_next;
734
g_free(e->ex_exec);
735
g_free(e->ex_unix);
736
g_free(e);
737
}
738
739
ip_cleanup(slirp);
740
ip6_cleanup(slirp);
741
m_cleanup(slirp);
742
tftp_cleanup(slirp);
743
744
g_rand_free(slirp->grand);
745
746
g_free(slirp->vdnssearch);
747
g_free(slirp->tftp_prefix);
748
g_free(slirp->bootp_filename);
749
g_free(slirp->vdomainname);
750
g_free(slirp);
751
}
752
753
#define CONN_CANFSEND(so) \
754
(((so)->so_state & (SS_FCANTSENDMORE | SS_ISFCONNECTED)) == SS_ISFCONNECTED)
755
#define CONN_CANFRCV(so) \
756
(((so)->so_state & (SS_FCANTRCVMORE | SS_ISFCONNECTED)) == SS_ISFCONNECTED)
757
758
static void slirp_update_timeout(Slirp *slirp, uint32_t *timeout)
759
{
760
uint32_t t;
761
762
if (*timeout <= TIMEOUT_FAST) {
763
return;
764
}
765
766
t = MIN(1000, *timeout);
767
768
/* If we have tcp timeout with slirp, then we will fill @timeout with
769
* more precise value.
770
*/
771
if (slirp->time_fasttimo) {
772
*timeout = TIMEOUT_FAST;
773
return;
774
}
775
if (slirp->do_slowtimo) {
776
t = MIN(TIMEOUT_SLOW, t);
777
}
778
*timeout = t;
779
}
780
781
void slirp_pollfds_fill(Slirp *slirp, uint32_t *timeout,
782
SlirpAddPollCb add_poll, void *opaque)
783
{
784
struct socket *so, *so_next;
785
786
/*
787
* First, TCP sockets
788
*/
789
790
/*
791
* *_slowtimo needs calling if there are IP fragments
792
* in the fragment queue, or there are TCP connections active
793
*/
794
slirp->do_slowtimo = ((slirp->tcb.so_next != &slirp->tcb) ||
795
(&slirp->ipq.ip_link != slirp->ipq.ip_link.next));
796
797
for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so_next) {
798
int events = 0;
799
800
so_next = so->so_next;
801
802
so->pollfds_idx = -1;
803
804
/*
805
* See if we need a tcp_fasttimo
806
*/
807
if (slirp->time_fasttimo == 0 && so->so_tcpcb->t_flags & TF_DELACK) {
808
slirp->time_fasttimo = curtime; /* Flag when want a fasttimo */
809
}
810
811
/*
812
* NOFDREF can include still connecting to local-host,
813
* newly socreated() sockets etc. Don't want to select these.
814
*/
815
if (so->so_state & SS_NOFDREF || so->s == -1) {
816
continue;
817
}
818
819
/*
820
* Set for reading sockets which are accepting
821
*/
822
if (so->so_state & SS_FACCEPTCONN) {
823
so->pollfds_idx = add_poll(
824
so->s, SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR, opaque);
825
continue;
826
}
827
828
/*
829
* Set for writing sockets which are connecting
830
*/
831
if (so->so_state & SS_ISFCONNECTING) {
832
so->pollfds_idx =
833
add_poll(so->s, SLIRP_POLL_OUT | SLIRP_POLL_ERR, opaque);
834
continue;
835
}
836
837
/*
838
* Set for writing if we are connected, can send more, and
839
* we have something to send
840
*/
841
if (CONN_CANFSEND(so) && so->so_rcv.sb_cc) {
842
events |= SLIRP_POLL_OUT | SLIRP_POLL_ERR;
843
}
844
845
/*
846
* Set for reading (and urgent data) if we are connected, can
847
* receive more, and we have room for it.
848
*
849
* If sb is already half full, we will wait for the guest to consume it,
850
* and notify again in sbdrop() when the sb becomes less than half full.
851
*/
852
if (CONN_CANFRCV(so) &&
853
(so->so_snd.sb_cc < (so->so_snd.sb_datalen / 2))) {
854
events |= SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR |
855
SLIRP_POLL_PRI;
856
}
857
858
if (events) {
859
so->pollfds_idx = add_poll(so->s, events, opaque);
860
}
861
}
862
863
/*
864
* UDP sockets
865
*/
866
for (so = slirp->udb.so_next; so != &slirp->udb; so = so_next) {
867
so_next = so->so_next;
868
869
so->pollfds_idx = -1;
870
871
/*
872
* See if it's timed out
873
*/
874
if (so->so_expire) {
875
if (so->so_expire <= curtime) {
876
udp_detach(so);
877
continue;
878
} else {
879
slirp->do_slowtimo = true; /* Let socket expire */
880
}
881
}
882
883
/*
884
* When UDP packets are received from over the
885
* link, they're sendto()'d straight away, so
886
* no need for setting for writing
887
* Limit the number of packets queued by this session
888
* to 4. Note that even though we try and limit this
889
* to 4 packets, the session could have more queued
890
* if the packets needed to be fragmented
891
* (XXX <= 4 ?)
892
*/
893
if ((so->so_state & SS_ISFCONNECTED) && so->so_queued <= 4) {
894
so->pollfds_idx = add_poll(
895
so->s, SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR, opaque);
896
}
897
}
898
899
/*
900
* ICMP sockets
901
*/
902
for (so = slirp->icmp.so_next; so != &slirp->icmp; so = so_next) {
903
so_next = so->so_next;
904
905
so->pollfds_idx = -1;
906
907
/*
908
* See if it's timed out
909
*/
910
if (so->so_expire) {
911
if (so->so_expire <= curtime) {
912
icmp_detach(so);
913
continue;
914
} else {
915
slirp->do_slowtimo = true; /* Let socket expire */
916
}
917
}
918
919
if (so->so_state & SS_ISFCONNECTED) {
920
so->pollfds_idx = add_poll(
921
so->s, SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR, opaque);
922
}
923
}
924
925
slirp_update_timeout(slirp, timeout);
926
}
927
928
void slirp_pollfds_poll(Slirp *slirp, int select_error,
929
SlirpGetREventsCb get_revents, void *opaque)
930
{
931
struct socket *so, *so_next;
932
int ret;
933
934
curtime = slirp->cb->clock_get_ns(slirp->opaque) / SCALE_MS;
935
936
/*
937
* See if anything has timed out
938
*/
939
if (slirp->time_fasttimo &&
940
((curtime - slirp->time_fasttimo) >= TIMEOUT_FAST)) {
941
tcp_fasttimo(slirp);
942
slirp->time_fasttimo = 0;
943
}
944
if (slirp->do_slowtimo &&
945
((curtime - slirp->last_slowtimo) >= TIMEOUT_SLOW)) {
946
ip_slowtimo(slirp);
947
tcp_slowtimo(slirp);
948
slirp->last_slowtimo = curtime;
949
}
950
951
/*
952
* Check sockets
953
*/
954
if (!select_error) {
955
/*
956
* Check TCP sockets
957
*/
958
for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so_next) {
959
int revents;
960
961
so_next = so->so_next;
962
963
revents = 0;
964
if (so->pollfds_idx != -1) {
965
revents = get_revents(so->pollfds_idx, opaque);
966
}
967
968
if (so->so_state & SS_NOFDREF || so->s == -1) {
969
continue;
970
}
971
972
#ifndef __APPLE__
973
/*
974
* Check for URG data
975
* This will soread as well, so no need to
976
* test for SLIRP_POLL_IN below if this succeeds.
977
*
978
* This is however disabled on MacOS, which apparently always
979
* reports data as PRI when it is the last data of the
980
* connection. We would then report it out of band, which the guest
981
* would most probably not be ready for.
982
*/
983
if (revents & SLIRP_POLL_PRI) {
984
ret = sorecvoob(so);
985
if (ret < 0) {
986
/* Socket error might have resulted in the socket being
987
* removed, do not try to do anything more with it. */
988
continue;
989
}
990
}
991
/*
992
* Check sockets for reading
993
*/
994
else
995
#endif
996
if (revents &
997
(SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR | SLIRP_POLL_PRI)) {
998
/*
999
* Check for incoming connections
1000
*/
1001
if (so->so_state & SS_FACCEPTCONN) {
1002
tcp_connect(so);
1003
continue;
1004
} /* else */
1005
ret = soread(so);
1006
1007
/* Output it if we read something */
1008
if (ret > 0) {
1009
tcp_output(sototcpcb(so));
1010
}
1011
if (ret < 0) {
1012
/* Socket error might have resulted in the socket being
1013
* removed, do not try to do anything more with it. */
1014
continue;
1015
}
1016
}
1017
1018
/*
1019
* Check sockets for writing
1020
*/
1021
if (!(so->so_state & SS_NOFDREF) &&
1022
(revents & (SLIRP_POLL_OUT | SLIRP_POLL_ERR))) {
1023
/*
1024
* Check for non-blocking, still-connecting sockets
1025
*/
1026
if (so->so_state & SS_ISFCONNECTING) {
1027
/* Connected */
1028
so->so_state &= ~SS_ISFCONNECTING;
1029
1030
ret = send(so->s, (const void *)&ret, 0, 0);
1031
if (ret < 0) {
1032
/* XXXXX Must fix, zero bytes is a NOP */
1033
if (errno == EAGAIN || errno == EWOULDBLOCK ||
1034
errno == EINPROGRESS || errno == ENOTCONN) {
1035
continue;
1036
}
1037
1038
/* else failed */
1039
so->so_state &= SS_PERSISTENT_MASK;
1040
so->so_state |= SS_NOFDREF;
1041
}
1042
/* else so->so_state &= ~SS_ISFCONNECTING; */
1043
1044
/*
1045
* Continue tcp_input
1046
*/
1047
tcp_input((struct mbuf *)NULL, sizeof(struct ip), so,
1048
so->so_ffamily);
1049
/* continue; */
1050
} else {
1051
ret = sowrite(so);
1052
if (ret > 0) {
1053
/* Call tcp_output in case we need to send a window
1054
* update to the guest, otherwise it will be stuck
1055
* until it sends a window probe. */
1056
tcp_output(sototcpcb(so));
1057
}
1058
}
1059
}
1060
}
1061
1062
/*
1063
* Now UDP sockets.
1064
* Incoming packets are sent straight away, they're not buffered.
1065
* Incoming UDP data isn't buffered either.
1066
*/
1067
for (so = slirp->udb.so_next; so != &slirp->udb; so = so_next) {
1068
int revents;
1069
1070
so_next = so->so_next;
1071
1072
revents = 0;
1073
if (so->pollfds_idx != -1) {
1074
revents = get_revents(so->pollfds_idx, opaque);
1075
}
1076
1077
if (so->s != -1 &&
1078
(revents & (SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR))) {
1079
sorecvfrom(so);
1080
}
1081
}
1082
1083
/*
1084
* Check incoming ICMP relies.
1085
*/
1086
for (so = slirp->icmp.so_next; so != &slirp->icmp; so = so_next) {
1087
int revents;
1088
1089
so_next = so->so_next;
1090
1091
revents = 0;
1092
if (so->pollfds_idx != -1) {
1093
revents = get_revents(so->pollfds_idx, opaque);
1094
}
1095
1096
if (so->s != -1 &&
1097
(revents & (SLIRP_POLL_IN | SLIRP_POLL_HUP | SLIRP_POLL_ERR))) {
1098
if (so->so_type == IPPROTO_IPV6 || so->so_type == IPPROTO_ICMPV6)
1099
icmp6_receive(so);
1100
else
1101
icmp_receive(so);
1102
}
1103
}
1104
}
1105
1106
if_start(slirp);
1107
}
1108
1109
static void arp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
1110
{
1111
const struct slirp_arphdr *ah =
1112
(const struct slirp_arphdr *)(pkt + ETH_HLEN);
1113
uint8_t arp_reply[MAX(2 + ETH_HLEN + sizeof(struct slirp_arphdr), 2 + 64)];
1114
struct ethhdr *reh = (struct ethhdr *)(arp_reply + 2);
1115
struct slirp_arphdr *rah = (struct slirp_arphdr *)(arp_reply + 2 + ETH_HLEN);
1116
int ar_op;
1117
struct gfwd_list *ex_ptr;
1118
1119
if (!slirp->in_enabled) {
1120
return;
1121
}
1122
1123
if (pkt_len < ETH_HLEN + sizeof(struct slirp_arphdr)) {
1124
return; /* packet too short */
1125
}
1126
1127
ar_op = ntohs(ah->ar_op);
1128
switch (ar_op) {
1129
case ARPOP_REQUEST:
1130
if (ah->ar_tip == ah->ar_sip) {
1131
/* Gratuitous ARP */
1132
arp_table_add(slirp, ah->ar_sip, ah->ar_sha);
1133
return;
1134
}
1135
1136
if ((ah->ar_tip & slirp->vnetwork_mask.s_addr) ==
1137
slirp->vnetwork_addr.s_addr) {
1138
if (ah->ar_tip == slirp->vnameserver_addr.s_addr ||
1139
ah->ar_tip == slirp->vhost_addr.s_addr)
1140
goto arp_ok;
1141
/* TODO: IPv6 */
1142
for (ex_ptr = slirp->guestfwd_list; ex_ptr;
1143
ex_ptr = ex_ptr->ex_next) {
1144
if (ex_ptr->ex_addr.s_addr == ah->ar_tip)
1145
goto arp_ok;
1146
}
1147
return;
1148
arp_ok:
1149
memset(arp_reply, 0, sizeof(arp_reply));
1150
1151
arp_table_add(slirp, ah->ar_sip, ah->ar_sha);
1152
1153
/* ARP request for alias/dns mac address */
1154
memcpy(reh->h_dest, pkt + ETH_ALEN, ETH_ALEN);
1155
memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
1156
memcpy(&reh->h_source[2], &ah->ar_tip, 4);
1157
reh->h_proto = htons(ETH_P_ARP);
1158
1159
rah->ar_hrd = htons(1);
1160
rah->ar_pro = htons(ETH_P_IP);
1161
rah->ar_hln = ETH_ALEN;
1162
rah->ar_pln = 4;
1163
rah->ar_op = htons(ARPOP_REPLY);
1164
memcpy(rah->ar_sha, reh->h_source, ETH_ALEN);
1165
rah->ar_sip = ah->ar_tip;
1166
memcpy(rah->ar_tha, ah->ar_sha, ETH_ALEN);
1167
rah->ar_tip = ah->ar_sip;
1168
slirp_send_packet_all(slirp, arp_reply + 2, sizeof(arp_reply) - 2);
1169
}
1170
break;
1171
case ARPOP_REPLY:
1172
arp_table_add(slirp, ah->ar_sip, ah->ar_sha);
1173
break;
1174
default:
1175
break;
1176
}
1177
}
1178
1179
void slirp_input(Slirp *slirp, const uint8_t *pkt, int pkt_len)
1180
{
1181
struct mbuf *m;
1182
int proto;
1183
1184
if (pkt_len < ETH_HLEN)
1185
return;
1186
1187
proto = (((uint16_t)pkt[12]) << 8) + pkt[13];
1188
switch (proto) {
1189
case ETH_P_ARP:
1190
arp_input(slirp, pkt, pkt_len);
1191
break;
1192
case ETH_P_IP:
1193
case ETH_P_IPV6:
1194
m = m_get(slirp);
1195
if (!m)
1196
return;
1197
/* Note: we add 2 to align the IP header on 8 bytes despite the ethernet
1198
* header, and add the margin for the tcpiphdr overhead */
1199
if (M_FREEROOM(m) < pkt_len + TCPIPHDR_DELTA + 2) {
1200
m_inc(m, pkt_len + TCPIPHDR_DELTA + 2);
1201
}
1202
m->m_len = pkt_len + TCPIPHDR_DELTA + 2;
1203
memcpy(m->m_data + TCPIPHDR_DELTA + 2, pkt, pkt_len);
1204
1205
m->m_data += TCPIPHDR_DELTA + 2 + ETH_HLEN;
1206
m->m_len -= TCPIPHDR_DELTA + 2 + ETH_HLEN;
1207
1208
if (proto == ETH_P_IP) {
1209
ip_input(m);
1210
} else if (proto == ETH_P_IPV6) {
1211
ip6_input(m);
1212
}
1213
break;
1214
1215
case ETH_P_NCSI:
1216
ncsi_input(slirp, pkt, pkt_len);
1217
break;
1218
1219
default:
1220
break;
1221
}
1222
}
1223
1224
/* Prepare the IPv4 packet to be sent to the ethernet device. Returns 1 if no
1225
* packet should be sent, 0 if the packet must be re-queued, 2 if the packet
1226
* is ready to go.
1227
*/
1228
static int if_encap4(Slirp *slirp, struct mbuf *ifm, struct ethhdr *eh,
1229
uint8_t ethaddr[ETH_ALEN])
1230
{
1231
const struct ip *iph = (const struct ip *)ifm->m_data;
1232
1233
if (!arp_table_search(slirp, iph->ip_dst.s_addr, ethaddr)) {
1234
uint8_t arp_req[2 + ETH_HLEN + sizeof(struct slirp_arphdr)];
1235
struct ethhdr *reh = (struct ethhdr *)(arp_req + 2);
1236
struct slirp_arphdr *rah = (struct slirp_arphdr *)(arp_req + 2 + ETH_HLEN);
1237
1238
if (!ifm->resolution_requested) {
1239
/* If the client addr is not known, send an ARP request */
1240
memset(reh->h_dest, 0xff, ETH_ALEN);
1241
memcpy(reh->h_source, special_ethaddr, ETH_ALEN - 4);
1242
memcpy(&reh->h_source[2], &slirp->vhost_addr, 4);
1243
reh->h_proto = htons(ETH_P_ARP);
1244
rah->ar_hrd = htons(1);
1245
rah->ar_pro = htons(ETH_P_IP);
1246
rah->ar_hln = ETH_ALEN;
1247
rah->ar_pln = 4;
1248
rah->ar_op = htons(ARPOP_REQUEST);
1249
1250
/* source hw addr */
1251
memcpy(rah->ar_sha, special_ethaddr, ETH_ALEN - 4);
1252
memcpy(&rah->ar_sha[2], &slirp->vhost_addr, 4);
1253
1254
/* source IP */
1255
rah->ar_sip = slirp->vhost_addr.s_addr;
1256
1257
/* target hw addr (none) */
1258
memset(rah->ar_tha, 0, ETH_ALEN);
1259
1260
/* target IP */
1261
rah->ar_tip = iph->ip_dst.s_addr;
1262
slirp->client_ipaddr = iph->ip_dst;
1263
slirp_send_packet_all(slirp, arp_req + 2, sizeof(arp_req) - 2);
1264
ifm->resolution_requested = true;
1265
1266
/* Expire request and drop outgoing packet after 1 second */
1267
ifm->expiration_date =
1268
slirp->cb->clock_get_ns(slirp->opaque) + 1000000000ULL;
1269
}
1270
return 0;
1271
} else {
1272
memcpy(eh->h_source, special_ethaddr, ETH_ALEN - 4);
1273
/* XXX: not correct */
1274
memcpy(&eh->h_source[2], &slirp->vhost_addr, 4);
1275
eh->h_proto = htons(ETH_P_IP);
1276
1277
/* Send this */
1278
return 2;
1279
}
1280
}
1281
1282
/* Prepare the IPv6 packet to be sent to the ethernet device. Returns 1 if no
1283
* packet should be sent, 0 if the packet must be re-queued, 2 if the packet
1284
* is ready to go.
1285
*/
1286
static int if_encap6(Slirp *slirp, struct mbuf *ifm, struct ethhdr *eh,
1287
uint8_t ethaddr[ETH_ALEN])
1288
{
1289
const struct ip6 *ip6h = mtod(ifm, const struct ip6 *);
1290
if (!ndp_table_search(slirp, ip6h->ip_dst, ethaddr)) {
1291
if (!ifm->resolution_requested) {
1292
ndp_send_ns(slirp, ip6h->ip_dst);
1293
ifm->resolution_requested = true;
1294
ifm->expiration_date =
1295
slirp->cb->clock_get_ns(slirp->opaque) + 1000000000ULL;
1296
}
1297
return 0;
1298
} else {
1299
eh->h_proto = htons(ETH_P_IPV6);
1300
in6_compute_ethaddr(ip6h->ip_src, eh->h_source);
1301
1302
/* Send this */
1303
return 2;
1304
}
1305
}
1306
1307
/* Output the IP packet to the ethernet device. Returns 0 if the packet must be
1308
* re-queued.
1309
*/
1310
int if_encap(Slirp *slirp, struct mbuf *ifm)
1311
{
1312
uint8_t buf[IF_MTU_MAX + 100];
1313
struct ethhdr *eh = (struct ethhdr *)(buf + 2);
1314
uint8_t ethaddr[ETH_ALEN];
1315
const struct ip *iph = (const struct ip *)ifm->m_data;
1316
int ret;
1317
char ethaddr_str[ETH_ADDRSTRLEN];
1318
1319
if (ifm->m_len + ETH_HLEN > sizeof(buf) - 2) {
1320
return 1;
1321
}
1322
1323
switch (iph->ip_v) {
1324
case IPVERSION:
1325
ret = if_encap4(slirp, ifm, eh, ethaddr);
1326
if (ret < 2) {
1327
return ret;
1328
}
1329
break;
1330
1331
case IP6VERSION:
1332
ret = if_encap6(slirp, ifm, eh, ethaddr);
1333
if (ret < 2) {
1334
return ret;
1335
}
1336
break;
1337
1338
default:
1339
g_assert_not_reached();
1340
}
1341
1342
memcpy(eh->h_dest, ethaddr, ETH_ALEN);
1343
DEBUG_ARG("src = %s", slirp_ether_ntoa(eh->h_source, ethaddr_str,
1344
sizeof(ethaddr_str)));
1345
DEBUG_ARG("dst = %s", slirp_ether_ntoa(eh->h_dest, ethaddr_str,
1346
sizeof(ethaddr_str)));
1347
memcpy(buf + 2 + sizeof(struct ethhdr), ifm->m_data, ifm->m_len);
1348
slirp_send_packet_all(slirp, buf + 2, ifm->m_len + ETH_HLEN);
1349
return 1;
1350
}
1351
1352
/* Drop host forwarding rule, return 0 if found. */
1353
int slirp_remove_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,
1354
int host_port)
1355
{
1356
struct socket *so;
1357
struct socket *head = (is_udp ? &slirp->udb : &slirp->tcb);
1358
struct sockaddr_in addr;
1359
int port = htons(host_port);
1360
socklen_t addr_len;
1361
1362
for (so = head->so_next; so != head; so = so->so_next) {
1363
addr_len = sizeof(addr);
1364
if ((so->so_state & SS_HOSTFWD) &&
1365
getsockname(so->s, (struct sockaddr *)&addr, &addr_len) == 0 &&
1366
addr_len == sizeof(addr) &&
1367
addr.sin_family == AF_INET &&
1368
addr.sin_addr.s_addr == host_addr.s_addr &&
1369
addr.sin_port == port) {
1370
so->slirp->cb->unregister_poll_fd(so->s, so->slirp->opaque);
1371
closesocket(so->s);
1372
sofree(so);
1373
return 0;
1374
}
1375
}
1376
1377
return -1;
1378
}
1379
1380
int slirp_add_hostfwd(Slirp *slirp, int is_udp, struct in_addr host_addr,
1381
int host_port, struct in_addr guest_addr, int guest_port)
1382
{
1383
if (!guest_addr.s_addr) {
1384
guest_addr = slirp->vdhcp_startaddr;
1385
}
1386
if (is_udp) {
1387
if (!udp_listen(slirp, host_addr.s_addr, htons(host_port),
1388
guest_addr.s_addr, htons(guest_port), SS_HOSTFWD))
1389
return -1;
1390
} else {
1391
if (!tcp_listen(slirp, host_addr.s_addr, htons(host_port),
1392
guest_addr.s_addr, htons(guest_port), SS_HOSTFWD))
1393
return -1;
1394
}
1395
return 0;
1396
}
1397
1398
int slirp_remove_hostxfwd(Slirp *slirp,
1399
const struct sockaddr *haddr, socklen_t haddrlen,
1400
int flags)
1401
{
1402
struct socket *so;
1403
struct socket *head = (flags & SLIRP_HOSTFWD_UDP ? &slirp->udb : &slirp->tcb);
1404
struct sockaddr_storage addr;
1405
socklen_t addr_len;
1406
1407
for (so = head->so_next; so != head; so = so->so_next) {
1408
addr_len = sizeof(addr);
1409
if ((so->so_state & SS_HOSTFWD) &&
1410
getsockname(so->s, (struct sockaddr *)&addr, &addr_len) == 0 &&
1411
sockaddr_equal(&addr, (const struct sockaddr_storage *) haddr)) {
1412
so->slirp->cb->unregister_poll_fd(so->s, so->slirp->opaque);
1413
closesocket(so->s);
1414
sofree(so);
1415
return 0;
1416
}
1417
}
1418
1419
return -1;
1420
}
1421
1422
int slirp_add_hostxfwd(Slirp *slirp,
1423
const struct sockaddr *haddr, socklen_t haddrlen,
1424
const struct sockaddr *gaddr, socklen_t gaddrlen,
1425
int flags)
1426
{
1427
struct sockaddr_in gdhcp_addr;
1428
int fwd_flags = SS_HOSTFWD;
1429
1430
if (flags & SLIRP_HOSTFWD_V6ONLY)
1431
fwd_flags |= SS_HOSTFWD_V6ONLY;
1432
1433
if (gaddr->sa_family == AF_INET) {
1434
const struct sockaddr_in *gaddr_in = (const struct sockaddr_in *) gaddr;
1435
1436
if (gaddrlen < sizeof(struct sockaddr_in)) {
1437
errno = EINVAL;
1438
return -1;
1439
}
1440
1441
if (!gaddr_in->sin_addr.s_addr) {
1442
gdhcp_addr = *gaddr_in;
1443
gdhcp_addr.sin_addr = slirp->vdhcp_startaddr;
1444
gaddr = (struct sockaddr *) &gdhcp_addr;
1445
gaddrlen = sizeof(gdhcp_addr);
1446
}
1447
} else {
1448
if (gaddrlen < sizeof(struct sockaddr_in6)) {
1449
errno = EINVAL;
1450
return -1;
1451
}
1452
1453
/*
1454
* Libslirp currently only provides a stateless DHCPv6 server, thus
1455
* we can't translate "addr-any" to the guest here. Instead, we defer
1456
* performing the translation to when it's needed. See
1457
* soassign_guest_addr_if_needed().
1458
*/
1459
}
1460
1461
if (flags & SLIRP_HOSTFWD_UDP) {
1462
if (!udpx_listen(slirp, haddr, haddrlen,
1463
gaddr, gaddrlen,
1464
fwd_flags))
1465
return -1;
1466
} else {
1467
if (!tcpx_listen(slirp, haddr, haddrlen,
1468
gaddr, gaddrlen,
1469
fwd_flags))
1470
return -1;
1471
}
1472
return 0;
1473
}
1474
1475
/* TODO: IPv6 */
1476
static bool check_guestfwd(Slirp *slirp, struct in_addr *guest_addr,
1477
int guest_port)
1478
{
1479
struct gfwd_list *tmp_ptr;
1480
1481
if (!guest_addr->s_addr) {
1482
guest_addr->s_addr = slirp->vnetwork_addr.s_addr |
1483
(htonl(0x0204) & ~slirp->vnetwork_mask.s_addr);
1484
}
1485
if ((guest_addr->s_addr & slirp->vnetwork_mask.s_addr) !=
1486
slirp->vnetwork_addr.s_addr ||
1487
guest_addr->s_addr == slirp->vhost_addr.s_addr ||
1488
guest_addr->s_addr == slirp->vnameserver_addr.s_addr) {
1489
return false;
1490
}
1491
1492
/* check if the port is "bound" */
1493
for (tmp_ptr = slirp->guestfwd_list; tmp_ptr; tmp_ptr = tmp_ptr->ex_next) {
1494
if (guest_port == tmp_ptr->ex_fport &&
1495
guest_addr->s_addr == tmp_ptr->ex_addr.s_addr)
1496
return false;
1497
}
1498
1499
return true;
1500
}
1501
1502
int slirp_add_exec(Slirp *slirp, const char *cmdline,
1503
struct in_addr *guest_addr, int guest_port)
1504
{
1505
if (!check_guestfwd(slirp, guest_addr, guest_port)) {
1506
return -1;
1507
}
1508
1509
add_exec(&slirp->guestfwd_list, cmdline, *guest_addr, htons(guest_port));
1510
return 0;
1511
}
1512
1513
int slirp_add_unix(Slirp *slirp, const char *unixsock,
1514
struct in_addr *guest_addr, int guest_port)
1515
{
1516
#ifdef G_OS_UNIX
1517
if (!check_guestfwd(slirp, guest_addr, guest_port)) {
1518
return -1;
1519
}
1520
1521
add_unix(&slirp->guestfwd_list, unixsock, *guest_addr, htons(guest_port));
1522
return 0;
1523
#else
1524
g_warn_if_reached();
1525
return -1;
1526
#endif
1527
}
1528
1529
int slirp_add_guestfwd(Slirp *slirp, SlirpWriteCb write_cb, void *opaque,
1530
struct in_addr *guest_addr, int guest_port)
1531
{
1532
if (!check_guestfwd(slirp, guest_addr, guest_port)) {
1533
return -1;
1534
}
1535
1536
add_guestfwd(&slirp->guestfwd_list, write_cb, opaque, *guest_addr,
1537
htons(guest_port));
1538
return 0;
1539
}
1540
1541
int slirp_remove_guestfwd(Slirp *slirp, struct in_addr guest_addr,
1542
int guest_port)
1543
{
1544
return remove_guestfwd(&slirp->guestfwd_list, guest_addr,
1545
htons(guest_port));
1546
}
1547
1548
slirp_ssize_t slirp_send(struct socket *so, const void *buf, size_t len, int flags)
1549
{
1550
if (so->s == -1 && so->guestfwd) {
1551
/* XXX this blocks entire thread. Rewrite to use
1552
* qemu_chr_fe_write and background I/O callbacks */
1553
so->guestfwd->write_cb(buf, len, so->guestfwd->opaque);
1554
return len;
1555
}
1556
1557
if (so->s == -1) {
1558
/*
1559
* This should in theory not happen but it is hard to be
1560
* sure because some code paths will end up with so->s == -1
1561
* on a failure but don't dispose of the struct socket.
1562
* Check specifically, so we don't pass -1 to send().
1563
*/
1564
errno = EBADF;
1565
return -1;
1566
}
1567
1568
return send(so->s, buf, len, flags);
1569
}
1570
1571
struct socket *slirp_find_ctl_socket(Slirp *slirp, struct in_addr guest_addr,
1572
int guest_port)
1573
{
1574
struct socket *so;
1575
1576
/* TODO: IPv6 */
1577
for (so = slirp->tcb.so_next; so != &slirp->tcb; so = so->so_next) {
1578
if (so->so_faddr.s_addr == guest_addr.s_addr &&
1579
htons(so->so_fport) == guest_port) {
1580
return so;
1581
}
1582
}
1583
return NULL;
1584
}
1585
1586
size_t slirp_socket_can_recv(Slirp *slirp, struct in_addr guest_addr,
1587
int guest_port)
1588
{
1589
struct iovec iov[2];
1590
struct socket *so;
1591
1592
so = slirp_find_ctl_socket(slirp, guest_addr, guest_port);
1593
1594
if (!so || so->so_state & SS_NOFDREF) {
1595
return 0;
1596
}
1597
1598
if (!CONN_CANFRCV(so) || so->so_snd.sb_cc >= (so->so_snd.sb_datalen / 2)) {
1599
/* If the sb is already half full, we will wait for the guest to consume it,
1600
* and notify again in sbdrop() when the sb becomes less than half full. */
1601
return 0;
1602
}
1603
1604
return sopreprbuf(so, iov, NULL);
1605
}
1606
1607
void slirp_socket_recv(Slirp *slirp, struct in_addr guest_addr, int guest_port,
1608
const uint8_t *buf, int size)
1609
{
1610
int ret;
1611
struct socket *so = slirp_find_ctl_socket(slirp, guest_addr, guest_port);
1612
1613
if (!so)
1614
return;
1615
1616
ret = soreadbuf(so, (const char *)buf, size);
1617
1618
if (ret > 0)
1619
tcp_output(sototcpcb(so));
1620
}
1621
1622
void slirp_send_packet_all(Slirp *slirp, const void *buf, size_t len)
1623
{
1624
slirp_ssize_t ret;
1625
1626
if (len < ETH_MINLEN) {
1627
char tmp[ETH_MINLEN];
1628
memcpy(tmp, buf, len);
1629
memset(tmp + len, 0, ETH_MINLEN - len);
1630
1631
ret = slirp->cb->send_packet(tmp, ETH_MINLEN, slirp->opaque);
1632
} else {
1633
ret = slirp->cb->send_packet(buf, len, slirp->opaque);
1634
}
1635
1636
if (ret < 0) {
1637
g_critical("Failed to send packet, ret: %ld", (long)ret);
1638
} else if (ret < len) {
1639
DEBUG_ERROR("send_packet() didn't send all data: %ld < %lu", (long)ret,
1640
(unsigned long)len);
1641
}
1642
}
1643
1644