Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
folium-app
GitHub Repository: folium-app/Folium
Path: blob/a-new-beginning/SharedDependencies/Sources/libslirp/mbuf.c
2 views
1
/* SPDX-License-Identifier: BSD-3-Clause */
2
/*
3
* Copyright (c) 1995 Danny Gasparovski
4
*/
5
6
/*
7
* mbuf's in SLiRP are much simpler than the real mbufs in
8
* FreeBSD. They are fixed size, determined by the MTU,
9
* so that one whole packet can fit. Mbuf's cannot be
10
* chained together. If there's more data than the mbuf
11
* could hold, an external g_malloced buffer is pointed to
12
* by m_ext (and the data pointers) and M_EXT is set in
13
* the flags
14
*/
15
16
#include "slirp.h"
17
18
#define MBUF_THRESH 30
19
20
/*
21
* Find a nice value for msize
22
*/
23
#define SLIRP_MSIZE(mtu) \
24
(offsetof(struct mbuf, m_dat) + IF_MAXLINKHDR + TCPIPHDR_DELTA + (mtu))
25
26
void m_init(Slirp *slirp)
27
{
28
slirp->m_freelist.qh_link = slirp->m_freelist.qh_rlink = &slirp->m_freelist;
29
slirp->m_usedlist.qh_link = slirp->m_usedlist.qh_rlink = &slirp->m_usedlist;
30
}
31
32
static void m_cleanup_list(struct slirp_quehead *list_head, bool pkts)
33
{
34
struct mbuf *m, *next, *next2;
35
bool last;
36
37
m = (struct mbuf *)list_head->qh_link;
38
while ((struct slirp_quehead *)m != list_head) {
39
next = m->m_next;
40
41
last = false;
42
while (1) {
43
next2 = m->m_nextpkt;
44
45
if (pkts) {
46
ifs_remque(m);
47
last = next2 == m;
48
} else {
49
last = true;
50
}
51
52
if (m->m_flags & M_EXT) {
53
g_free(m->m_ext);
54
}
55
56
g_free(m);
57
58
if (last)
59
break;
60
m = next2;
61
};
62
63
m = next;
64
}
65
list_head->qh_link = list_head;
66
list_head->qh_rlink = list_head;
67
}
68
69
void m_cleanup(Slirp *slirp)
70
{
71
m_cleanup_list(&slirp->m_usedlist, false);
72
m_cleanup_list(&slirp->m_freelist, false);
73
m_cleanup_list(&slirp->if_batchq, true);
74
m_cleanup_list(&slirp->if_fastq, true);
75
}
76
77
/*
78
* Get an mbuf from the free list, if there are none
79
* allocate one
80
*
81
* Because fragmentation can occur if we alloc new mbufs and
82
* free old mbufs, we mark all mbufs above mbuf_thresh as M_DOFREE,
83
* which tells m_free to actually g_free() it
84
*/
85
struct mbuf *m_get(Slirp *slirp)
86
{
87
register struct mbuf *m;
88
int flags = 0;
89
90
DEBUG_CALL("m_get");
91
92
if (MBUF_DEBUG || slirp->m_freelist.qh_link == &slirp->m_freelist) {
93
m = g_malloc(SLIRP_MSIZE(slirp->if_mtu));
94
slirp->mbuf_alloced++;
95
if (MBUF_DEBUG || slirp->mbuf_alloced > MBUF_THRESH)
96
flags = M_DOFREE;
97
m->slirp = slirp;
98
} else {
99
m = (struct mbuf *)slirp->m_freelist.qh_link;
100
slirp_remque(m);
101
}
102
103
/* Insert it in the used list */
104
slirp_insque(m, &slirp->m_usedlist);
105
m->m_flags = (flags | M_USEDLIST);
106
107
/* Initialise it */
108
m->m_size = SLIRP_MSIZE(slirp->if_mtu) - offsetof(struct mbuf, m_dat);
109
m->m_data = m->m_dat;
110
m->m_len = 0;
111
m->m_nextpkt = NULL;
112
m->m_prevpkt = NULL;
113
m->resolution_requested = false;
114
m->expiration_date = (uint64_t)-1;
115
DEBUG_ARG("m = %p", m);
116
return m;
117
}
118
119
void m_free(struct mbuf *m)
120
{
121
DEBUG_CALL("m_free");
122
DEBUG_ARG("m = %p", m);
123
124
if (m) {
125
/* Remove from m_usedlist */
126
if (m->m_flags & M_USEDLIST)
127
slirp_remque(m);
128
129
/* If it's M_EXT, free() it */
130
if (m->m_flags & M_EXT) {
131
g_free(m->m_ext);
132
m->m_flags &= ~M_EXT;
133
}
134
/*
135
* Either free() it or put it on the free list
136
*/
137
if (m->m_flags & M_DOFREE) {
138
m->slirp->mbuf_alloced--;
139
g_free(m);
140
} else if ((m->m_flags & M_FREELIST) == 0) {
141
slirp_insque(m, &m->slirp->m_freelist);
142
m->m_flags = M_FREELIST; /* Clobber other flags */
143
}
144
} /* if(m) */
145
}
146
147
/*
148
* Copy data from one mbuf to the end of
149
* the other.. if result is too big for one mbuf, allocate
150
* an M_EXT data segment
151
*/
152
void m_cat(struct mbuf *m, struct mbuf *n)
153
{
154
/*
155
* If there's no room, realloc
156
*/
157
if (M_FREEROOM(m) < n->m_len)
158
m_inc(m, m->m_len + n->m_len);
159
160
memcpy(m->m_data + m->m_len, n->m_data, n->m_len);
161
m->m_len += n->m_len;
162
163
m_free(n);
164
}
165
166
167
/* make m 'size' bytes large from m_data */
168
void m_inc(struct mbuf *m, int size)
169
{
170
int gapsize;
171
172
/* some compilers throw up on gotos. This one we can fake. */
173
if (M_ROOM(m) >= size) {
174
return;
175
}
176
177
if (m->m_flags & M_EXT) {
178
gapsize = m->m_data - m->m_ext;
179
m->m_ext = g_realloc(m->m_ext, size + gapsize);
180
} else {
181
gapsize = m->m_data - m->m_dat;
182
m->m_ext = g_malloc(size + gapsize);
183
memcpy(m->m_ext, m->m_dat, m->m_size);
184
m->m_flags |= M_EXT;
185
}
186
187
m->m_data = m->m_ext + gapsize;
188
m->m_size = size + gapsize;
189
}
190
191
192
void m_adj(struct mbuf *m, int len)
193
{
194
if (m == NULL)
195
return;
196
if (len >= 0) {
197
/* Trim from head */
198
m->m_data += len;
199
m->m_len -= len;
200
} else {
201
/* Trim from tail */
202
len = -len;
203
m->m_len -= len;
204
}
205
}
206
207
208
/*
209
* Copy len bytes from m, starting off bytes into n
210
*/
211
int m_copy(struct mbuf *n, struct mbuf *m, int off, int len)
212
{
213
if (len > M_FREEROOM(n))
214
return -1;
215
216
memcpy((n->m_data + n->m_len), (m->m_data + off), len);
217
n->m_len += len;
218
return 0;
219
}
220
221
222
struct mbuf *dtom(Slirp *slirp, void *dat)
223
{
224
struct mbuf *m;
225
226
DEBUG_CALL("dtom");
227
DEBUG_ARG("dat = %p", dat);
228
229
/* bug corrected for M_EXT buffers */
230
for (m = (struct mbuf *)slirp->m_usedlist.qh_link;
231
(struct slirp_quehead *)m != &slirp->m_usedlist; m = m->m_next) {
232
if (m->m_flags & M_EXT) {
233
if ((char *)dat >= m->m_ext && (char *)dat < (m->m_ext + m->m_size))
234
return m;
235
} else {
236
if ((char *)dat >= m->m_dat && (char *)dat < (m->m_dat + m->m_size))
237
return m;
238
}
239
}
240
241
DEBUG_ERROR("dtom failed");
242
243
return (struct mbuf *)0;
244
}
245
246
struct mbuf *m_dup(Slirp *slirp, struct mbuf *m,
247
bool copy_header,
248
size_t header_size)
249
{
250
struct mbuf *n;
251
int mcopy_result;
252
253
/* The previous mbuf was supposed to have it already, we can check it along
254
* the way */
255
assert(M_ROOMBEFORE(m) >= header_size);
256
257
n = m_get(slirp);
258
m_inc(n, m->m_len + header_size);
259
260
if (copy_header) {
261
m->m_len += header_size;
262
m->m_data -= header_size;
263
mcopy_result = m_copy(n, m, 0, m->m_len);
264
n->m_data += header_size;
265
n->m_len -= header_size;
266
m->m_len -= header_size;
267
m->m_data += header_size;
268
} else {
269
n->m_data += header_size;
270
mcopy_result = m_copy(n, m, 0, m->m_len);
271
}
272
g_assert(mcopy_result == 0);
273
274
return n;
275
}
276
277
void *mtod_check(struct mbuf *m, size_t len)
278
{
279
if (m->m_len >= len) {
280
return m->m_data;
281
}
282
283
DEBUG_ERROR("mtod failed");
284
285
return NULL;
286
}
287
288
void *m_end(struct mbuf *m)
289
{
290
return m->m_data + m->m_len;
291
}
292
293