Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
folium-app
GitHub Repository: folium-app/Folium
Path: blob/a-new-beginning/SharedDependencies/Sources/libslirp/state.c
2 views
1
/* SPDX-License-Identifier: MIT */
2
/*
3
* libslirp
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
#include "vmstate.h"
27
#include "stream.h"
28
29
static int slirp_tcp_post_load(void *opaque, int version)
30
{
31
tcp_template((struct tcpcb *)opaque);
32
33
return 0;
34
}
35
36
static const VMStateDescription vmstate_slirp_tcp = {
37
.name = "slirp-tcp",
38
.version_id = 0,
39
.post_load = slirp_tcp_post_load,
40
.fields = (VMStateField[]){ VMSTATE_INT16(t_state, struct tcpcb),
41
VMSTATE_INT16_ARRAY(t_timer, struct tcpcb,
42
TCPT_NTIMERS),
43
VMSTATE_INT16(t_rxtshift, struct tcpcb),
44
VMSTATE_INT16(t_rxtcur, struct tcpcb),
45
VMSTATE_INT16(t_dupacks, struct tcpcb),
46
VMSTATE_UINT16(t_maxseg, struct tcpcb),
47
VMSTATE_UINT8(t_force, struct tcpcb),
48
VMSTATE_UINT16(t_flags, struct tcpcb),
49
VMSTATE_UINT32(snd_una, struct tcpcb),
50
VMSTATE_UINT32(snd_nxt, struct tcpcb),
51
VMSTATE_UINT32(snd_up, struct tcpcb),
52
VMSTATE_UINT32(snd_wl1, struct tcpcb),
53
VMSTATE_UINT32(snd_wl2, struct tcpcb),
54
VMSTATE_UINT32(iss, struct tcpcb),
55
VMSTATE_UINT32(snd_wnd, struct tcpcb),
56
VMSTATE_UINT32(rcv_wnd, struct tcpcb),
57
VMSTATE_UINT32(rcv_nxt, struct tcpcb),
58
VMSTATE_UINT32(rcv_up, struct tcpcb),
59
VMSTATE_UINT32(irs, struct tcpcb),
60
VMSTATE_UINT32(rcv_adv, struct tcpcb),
61
VMSTATE_UINT32(snd_max, struct tcpcb),
62
VMSTATE_UINT32(snd_cwnd, struct tcpcb),
63
VMSTATE_UINT32(snd_ssthresh, struct tcpcb),
64
VMSTATE_INT16(t_idle, struct tcpcb),
65
VMSTATE_INT16(t_rtt, struct tcpcb),
66
VMSTATE_UINT32(t_rtseq, struct tcpcb),
67
VMSTATE_INT16(t_srtt, struct tcpcb),
68
VMSTATE_INT16(t_rttvar, struct tcpcb),
69
VMSTATE_UINT16(t_rttmin, struct tcpcb),
70
VMSTATE_UINT32(max_sndwnd, struct tcpcb),
71
VMSTATE_UINT8(t_oobflags, struct tcpcb),
72
VMSTATE_UINT8(t_iobc, struct tcpcb),
73
VMSTATE_INT16(t_softerror, struct tcpcb),
74
VMSTATE_UINT8(snd_scale, struct tcpcb),
75
VMSTATE_UINT8(rcv_scale, struct tcpcb),
76
VMSTATE_UINT8(request_r_scale, struct tcpcb),
77
VMSTATE_UINT8(requested_s_scale, struct tcpcb),
78
VMSTATE_UINT32(ts_recent, struct tcpcb),
79
VMSTATE_UINT32(ts_recent_age, struct tcpcb),
80
VMSTATE_UINT32(last_ack_sent, struct tcpcb),
81
VMSTATE_END_OF_LIST() }
82
};
83
84
/* The sbuf has a pair of pointers that are migrated as offsets;
85
* we calculate the offsets and restore the pointers using
86
* pre_save/post_load on a tmp structure.
87
*/
88
struct sbuf_tmp {
89
struct sbuf *parent;
90
uint32_t roff, woff;
91
};
92
93
static int sbuf_tmp_pre_save(void *opaque)
94
{
95
struct sbuf_tmp *tmp = opaque;
96
tmp->woff = tmp->parent->sb_wptr - tmp->parent->sb_data;
97
tmp->roff = tmp->parent->sb_rptr - tmp->parent->sb_data;
98
99
return 0;
100
}
101
102
static int sbuf_tmp_post_load(void *opaque, int version)
103
{
104
struct sbuf_tmp *tmp = opaque;
105
uint32_t requested_len = tmp->parent->sb_datalen;
106
107
/* Allocate the buffer space used by the field after the tmp */
108
sbreserve(tmp->parent, tmp->parent->sb_datalen);
109
110
if (tmp->woff >= requested_len || tmp->roff >= requested_len) {
111
g_critical("invalid sbuf offsets r/w=%u/%u len=%u", tmp->roff,
112
tmp->woff, requested_len);
113
return -EINVAL;
114
}
115
116
tmp->parent->sb_wptr = tmp->parent->sb_data + tmp->woff;
117
tmp->parent->sb_rptr = tmp->parent->sb_data + tmp->roff;
118
119
return 0;
120
}
121
122
123
static const VMStateDescription vmstate_slirp_sbuf_tmp = {
124
.name = "slirp-sbuf-tmp",
125
.post_load = sbuf_tmp_post_load,
126
.pre_save = sbuf_tmp_pre_save,
127
.version_id = 0,
128
.fields = (VMStateField[]){ VMSTATE_UINT32(woff, struct sbuf_tmp),
129
VMSTATE_UINT32(roff, struct sbuf_tmp),
130
VMSTATE_END_OF_LIST() }
131
};
132
133
static const VMStateDescription vmstate_slirp_sbuf = {
134
.name = "slirp-sbuf",
135
.version_id = 0,
136
.fields = (VMStateField[]){ VMSTATE_UINT32(sb_cc, struct sbuf),
137
VMSTATE_UINT32(sb_datalen, struct sbuf),
138
VMSTATE_WITH_TMP(struct sbuf, struct sbuf_tmp,
139
vmstate_slirp_sbuf_tmp),
140
VMSTATE_VBUFFER_UINT32(sb_data, struct sbuf, 0,
141
NULL, sb_datalen),
142
VMSTATE_END_OF_LIST() }
143
};
144
145
static bool slirp_older_than_v4(void *opaque, int version_id)
146
{
147
return version_id < 4;
148
}
149
150
static bool slirp_family_inet(void *opaque, int version_id)
151
{
152
union slirp_sockaddr *ssa = (union slirp_sockaddr *)opaque;
153
return ssa->ss.ss_family == AF_INET;
154
}
155
156
static int slirp_socket_pre_load(void *opaque)
157
{
158
struct socket *so = opaque;
159
160
tcp_attach(so);
161
/* Older versions don't load these fields */
162
so->so_ffamily = AF_INET;
163
so->so_lfamily = AF_INET;
164
return 0;
165
}
166
167
#ifndef _WIN32
168
#define VMSTATE_SIN4_ADDR(f, s, t) VMSTATE_UINT32_TEST(f, s, t)
169
#else
170
/* Win uses u_long rather than uint32_t - but it's still 32bits long */
171
#define VMSTATE_SIN4_ADDR(f, s, t) \
172
VMSTATE_SINGLE_TEST(f, s, t, 0, slirp_vmstate_info_uint32, u_long)
173
#endif
174
175
/* The OS provided ss_family field isn't that portable; it's size
176
* and type varies (16/8 bit, signed, unsigned)
177
* and the values it contains aren't fully portable.
178
*/
179
typedef struct SS_FamilyTmpStruct {
180
union slirp_sockaddr *parent;
181
uint16_t portable_family;
182
} SS_FamilyTmpStruct;
183
184
#define SS_FAMILY_MIG_IPV4 2 /* Linux, BSD, Win... */
185
#define SS_FAMILY_MIG_IPV6 10 /* Linux */
186
#define SS_FAMILY_MIG_OTHER 0xffff
187
188
static int ss_family_pre_save(void *opaque)
189
{
190
SS_FamilyTmpStruct *tss = opaque;
191
192
tss->portable_family = SS_FAMILY_MIG_OTHER;
193
194
if (tss->parent->ss.ss_family == AF_INET) {
195
tss->portable_family = SS_FAMILY_MIG_IPV4;
196
} else if (tss->parent->ss.ss_family == AF_INET6) {
197
tss->portable_family = SS_FAMILY_MIG_IPV6;
198
}
199
200
return 0;
201
}
202
203
static int ss_family_post_load(void *opaque, int version_id)
204
{
205
SS_FamilyTmpStruct *tss = opaque;
206
207
switch (tss->portable_family) {
208
case SS_FAMILY_MIG_IPV4:
209
tss->parent->ss.ss_family = AF_INET;
210
break;
211
case SS_FAMILY_MIG_IPV6:
212
case 23: /* compatibility: AF_INET6 from mingw */
213
case 28: /* compatibility: AF_INET6 from FreeBSD sys/socket.h */
214
tss->parent->ss.ss_family = AF_INET6;
215
break;
216
default:
217
g_critical("invalid ss_family type %x", tss->portable_family);
218
return -EINVAL;
219
}
220
221
return 0;
222
}
223
224
static const VMStateDescription vmstate_slirp_ss_family = {
225
.name = "slirp-socket-addr/ss_family",
226
.pre_save = ss_family_pre_save,
227
.post_load = ss_family_post_load,
228
.fields =
229
(VMStateField[]){ VMSTATE_UINT16(portable_family, SS_FamilyTmpStruct),
230
VMSTATE_END_OF_LIST() }
231
};
232
233
static const VMStateDescription vmstate_slirp_socket_addr = {
234
.name = "slirp-socket-addr",
235
.version_id = 4,
236
.fields =
237
(VMStateField[]){
238
VMSTATE_WITH_TMP(union slirp_sockaddr, SS_FamilyTmpStruct,
239
vmstate_slirp_ss_family),
240
VMSTATE_SIN4_ADDR(sin.sin_addr.s_addr, union slirp_sockaddr,
241
slirp_family_inet),
242
VMSTATE_UINT16_TEST(sin.sin_port, union slirp_sockaddr,
243
slirp_family_inet),
244
245
#if 0
246
/* Untested: Needs checking by someone with IPv6 test */
247
VMSTATE_BUFFER_TEST(sin6.sin6_addr, union slirp_sockaddr,
248
slirp_family_inet6),
249
VMSTATE_UINT16_TEST(sin6.sin6_port, union slirp_sockaddr,
250
slirp_family_inet6),
251
VMSTATE_UINT32_TEST(sin6.sin6_flowinfo, union slirp_sockaddr,
252
slirp_family_inet6),
253
VMSTATE_UINT32_TEST(sin6.sin6_scope_id, union slirp_sockaddr,
254
slirp_family_inet6),
255
#endif
256
257
VMSTATE_END_OF_LIST() }
258
};
259
260
static const VMStateDescription vmstate_slirp_socket = {
261
.name = "slirp-socket",
262
.version_id = 4,
263
.pre_load = slirp_socket_pre_load,
264
.fields =
265
(VMStateField[]){
266
VMSTATE_UINT32(so_urgc, struct socket),
267
/* Pre-v4 versions */
268
VMSTATE_SIN4_ADDR(so_faddr.s_addr, struct socket,
269
slirp_older_than_v4),
270
VMSTATE_SIN4_ADDR(so_laddr.s_addr, struct socket,
271
slirp_older_than_v4),
272
VMSTATE_UINT16_TEST(so_fport, struct socket, slirp_older_than_v4),
273
VMSTATE_UINT16_TEST(so_lport, struct socket, slirp_older_than_v4),
274
/* v4 and newer */
275
VMSTATE_STRUCT(fhost, struct socket, 4, vmstate_slirp_socket_addr,
276
union slirp_sockaddr),
277
VMSTATE_STRUCT(lhost, struct socket, 4, vmstate_slirp_socket_addr,
278
union slirp_sockaddr),
279
280
VMSTATE_UINT8(so_iptos, struct socket),
281
VMSTATE_UINT8(so_emu, struct socket),
282
VMSTATE_UINT8(so_type, struct socket),
283
VMSTATE_INT32(so_state, struct socket),
284
VMSTATE_STRUCT(so_rcv, struct socket, 0, vmstate_slirp_sbuf,
285
struct sbuf),
286
VMSTATE_STRUCT(so_snd, struct socket, 0, vmstate_slirp_sbuf,
287
struct sbuf),
288
VMSTATE_STRUCT_POINTER(so_tcpcb, struct socket, vmstate_slirp_tcp,
289
struct tcpcb),
290
VMSTATE_END_OF_LIST() }
291
};
292
293
static const VMStateDescription vmstate_slirp_bootp_client = {
294
.name = "slirp_bootpclient",
295
.fields = (VMStateField[]){ VMSTATE_UINT16(allocated, BOOTPClient),
296
VMSTATE_BUFFER(macaddr, BOOTPClient),
297
VMSTATE_END_OF_LIST() }
298
};
299
300
static const VMStateDescription vmstate_slirp = {
301
.name = "slirp",
302
.version_id = 4,
303
.fields = (VMStateField[]){ VMSTATE_UINT16_V(ip_id, Slirp, 2),
304
VMSTATE_STRUCT_ARRAY(
305
bootp_clients, Slirp, NB_BOOTP_CLIENTS, 3,
306
vmstate_slirp_bootp_client, BOOTPClient),
307
VMSTATE_END_OF_LIST() }
308
};
309
310
int slirp_state_save(Slirp *slirp, SlirpWriteCb write_cb, void *opaque)
311
{
312
struct gfwd_list *ex_ptr;
313
SlirpOStream f = {
314
.write_cb = write_cb,
315
.opaque = opaque,
316
};
317
318
for (ex_ptr = slirp->guestfwd_list; ex_ptr; ex_ptr = ex_ptr->ex_next)
319
if (ex_ptr->write_cb) {
320
struct socket *so;
321
so = slirp_find_ctl_socket(slirp, ex_ptr->ex_addr,
322
ntohs(ex_ptr->ex_fport));
323
if (!so) {
324
continue;
325
}
326
327
slirp_ostream_write_u8(&f, 42);
328
slirp_vmstate_save_state(&f, &vmstate_slirp_socket, so);
329
}
330
slirp_ostream_write_u8(&f, 0);
331
332
slirp_vmstate_save_state(&f, &vmstate_slirp, slirp);
333
334
return 0;
335
}
336
337
338
int slirp_state_load(Slirp *slirp, int version_id, SlirpReadCb read_cb,
339
void *opaque)
340
{
341
struct gfwd_list *ex_ptr;
342
SlirpIStream f = {
343
.read_cb = read_cb,
344
.opaque = opaque,
345
};
346
347
while (slirp_istream_read_u8(&f)) {
348
int ret;
349
struct socket *so = socreate(slirp, -1);
350
351
ret =
352
slirp_vmstate_load_state(&f, &vmstate_slirp_socket, so, version_id);
353
if (ret < 0) {
354
return ret;
355
}
356
357
if ((so->so_faddr.s_addr & slirp->vnetwork_mask.s_addr) !=
358
slirp->vnetwork_addr.s_addr) {
359
return -EINVAL;
360
}
361
for (ex_ptr = slirp->guestfwd_list; ex_ptr; ex_ptr = ex_ptr->ex_next) {
362
if (ex_ptr->write_cb &&
363
so->so_faddr.s_addr == ex_ptr->ex_addr.s_addr &&
364
so->so_fport == ex_ptr->ex_fport) {
365
break;
366
}
367
}
368
if (!ex_ptr) {
369
return -EINVAL;
370
}
371
372
so->guestfwd = ex_ptr;
373
}
374
375
return slirp_vmstate_load_state(&f, &vmstate_slirp, slirp, version_id);
376
}
377
378
int slirp_state_version(void)
379
{
380
return 4;
381
}
382
383