Revision 460fec67 slirp/tftp.c
b/slirp/tftp.c | ||
---|---|---|
25 | 25 |
#include <slirp.h> |
26 | 26 |
#include "qemu-common.h" |
27 | 27 |
|
28 |
struct tftp_session { |
|
29 |
int in_use; |
|
30 |
char *filename; |
|
31 |
|
|
32 |
struct in_addr client_ip; |
|
33 |
u_int16_t client_port; |
|
34 |
|
|
35 |
int timestamp; |
|
36 |
}; |
|
37 |
|
|
38 |
static struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX]; |
|
39 |
|
|
40 |
char *tftp_prefix; |
|
28 |
static inline int tftp_session_in_use(struct tftp_session *spt) |
|
29 |
{ |
|
30 |
return (spt->slirp != NULL); |
|
31 |
} |
|
41 | 32 |
|
42 |
static void tftp_session_update(struct tftp_session *spt) |
|
33 |
static inline void tftp_session_update(struct tftp_session *spt)
|
|
43 | 34 |
{ |
44 | 35 |
spt->timestamp = curtime; |
45 |
spt->in_use = 1; |
|
46 | 36 |
} |
47 | 37 |
|
48 | 38 |
static void tftp_session_terminate(struct tftp_session *spt) |
49 | 39 |
{ |
50 |
qemu_free(spt->filename); |
|
51 |
spt->in_use = 0;
|
|
40 |
qemu_free(spt->filename);
|
|
41 |
spt->slirp = NULL;
|
|
52 | 42 |
} |
53 | 43 |
|
54 |
static int tftp_session_allocate(struct tftp_t *tp) |
|
44 |
static int tftp_session_allocate(Slirp *slirp, struct tftp_t *tp)
|
|
55 | 45 |
{ |
56 | 46 |
struct tftp_session *spt; |
57 | 47 |
int k; |
58 | 48 |
|
59 | 49 |
for (k = 0; k < TFTP_SESSIONS_MAX; k++) { |
60 |
spt = &tftp_sessions[k]; |
|
50 |
spt = &slirp->tftp_sessions[k];
|
|
61 | 51 |
|
62 |
if (!spt->in_use)
|
|
52 |
if (!tftp_session_in_use(spt))
|
|
63 | 53 |
goto found; |
64 | 54 |
|
65 | 55 |
/* sessions time out after 5 inactive seconds */ |
... | ... | |
75 | 65 |
memset(spt, 0, sizeof(*spt)); |
76 | 66 |
memcpy(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip)); |
77 | 67 |
spt->client_port = tp->udp.uh_sport; |
68 |
spt->slirp = slirp; |
|
78 | 69 |
|
79 | 70 |
tftp_session_update(spt); |
80 | 71 |
|
81 | 72 |
return k; |
82 | 73 |
} |
83 | 74 |
|
84 |
static int tftp_session_find(struct tftp_t *tp) |
|
75 |
static int tftp_session_find(Slirp *slirp, struct tftp_t *tp)
|
|
85 | 76 |
{ |
86 | 77 |
struct tftp_session *spt; |
87 | 78 |
int k; |
88 | 79 |
|
89 | 80 |
for (k = 0; k < TFTP_SESSIONS_MAX; k++) { |
90 |
spt = &tftp_sessions[k]; |
|
81 |
spt = &slirp->tftp_sessions[k];
|
|
91 | 82 |
|
92 |
if (spt->in_use) {
|
|
83 |
if (tftp_session_in_use(spt)) {
|
|
93 | 84 |
if (!memcmp(&spt->client_ip, &tp->ip.ip_src, sizeof(spt->client_ip))) { |
94 | 85 |
if (spt->client_port == tp->udp.uh_sport) { |
95 | 86 |
return k; |
... | ... | |
133 | 124 |
struct tftp_t *tp; |
134 | 125 |
int n = 0; |
135 | 126 |
|
136 |
m = m_get(); |
|
127 |
m = m_get(spt->slirp);
|
|
137 | 128 |
|
138 | 129 |
if (!m) |
139 | 130 |
return -1; |
... | ... | |
172 | 163 |
struct tftp_t *tp; |
173 | 164 |
int nobytes; |
174 | 165 |
|
175 |
m = m_get(); |
|
166 |
m = m_get(spt->slirp);
|
|
176 | 167 |
|
177 | 168 |
if (!m) { |
178 | 169 |
goto out; |
... | ... | |
218 | 209 |
return -1; |
219 | 210 |
} |
220 | 211 |
|
221 |
m = m_get(); |
|
212 |
m = m_get(spt->slirp);
|
|
222 | 213 |
|
223 | 214 |
if (!m) { |
224 | 215 |
return -1; |
... | ... | |
266 | 257 |
return 0; |
267 | 258 |
} |
268 | 259 |
|
269 |
static void tftp_handle_rrq(struct tftp_t *tp, int pktlen) |
|
260 |
static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen)
|
|
270 | 261 |
{ |
271 | 262 |
struct tftp_session *spt; |
272 | 263 |
int s, k; |
273 | 264 |
size_t prefix_len; |
274 | 265 |
char *req_fname; |
275 | 266 |
|
276 |
s = tftp_session_allocate(tp); |
|
267 |
s = tftp_session_allocate(slirp, tp);
|
|
277 | 268 |
|
278 | 269 |
if (s < 0) { |
279 | 270 |
return; |
280 | 271 |
} |
281 | 272 |
|
282 |
spt = &tftp_sessions[s]; |
|
273 |
spt = &slirp->tftp_sessions[s];
|
|
283 | 274 |
|
284 | 275 |
/* unspecifed prefix means service disabled */ |
285 |
if (!tftp_prefix) { |
|
276 |
if (!slirp->tftp_prefix) {
|
|
286 | 277 |
tftp_send_error(spt, 2, "Access violation", tp); |
287 | 278 |
return; |
288 | 279 |
} |
... | ... | |
292 | 283 |
pktlen -= ((uint8_t *)&tp->x.tp_buf[0] - (uint8_t *)tp); |
293 | 284 |
|
294 | 285 |
/* prepend tftp_prefix */ |
295 |
prefix_len = strlen(tftp_prefix); |
|
286 |
prefix_len = strlen(slirp->tftp_prefix);
|
|
296 | 287 |
spt->filename = qemu_malloc(prefix_len + TFTP_FILENAME_MAX + 1); |
297 |
memcpy(spt->filename, tftp_prefix, prefix_len); |
|
288 |
memcpy(spt->filename, slirp->tftp_prefix, prefix_len);
|
|
298 | 289 |
|
299 | 290 |
/* get name */ |
300 | 291 |
req_fname = spt->filename + prefix_len; |
... | ... | |
375 | 366 |
tftp_send_data(spt, 1, tp); |
376 | 367 |
} |
377 | 368 |
|
378 |
static void tftp_handle_ack(struct tftp_t *tp, int pktlen) |
|
369 |
static void tftp_handle_ack(Slirp *slirp, struct tftp_t *tp, int pktlen)
|
|
379 | 370 |
{ |
380 | 371 |
int s; |
381 | 372 |
|
382 |
s = tftp_session_find(tp); |
|
373 |
s = tftp_session_find(slirp, tp);
|
|
383 | 374 |
|
384 | 375 |
if (s < 0) { |
385 | 376 |
return; |
386 | 377 |
} |
387 | 378 |
|
388 |
if (tftp_send_data(&tftp_sessions[s], |
|
379 |
if (tftp_send_data(&slirp->tftp_sessions[s],
|
|
389 | 380 |
ntohs(tp->x.tp_data.tp_block_nr) + 1, |
390 | 381 |
tp) < 0) { |
391 | 382 |
return; |
... | ... | |
398 | 389 |
|
399 | 390 |
switch(ntohs(tp->tp_op)) { |
400 | 391 |
case TFTP_RRQ: |
401 |
tftp_handle_rrq(tp, m->m_len); |
|
392 |
tftp_handle_rrq(m->slirp, tp, m->m_len);
|
|
402 | 393 |
break; |
403 | 394 |
|
404 | 395 |
case TFTP_ACK: |
405 |
tftp_handle_ack(tp, m->m_len); |
|
396 |
tftp_handle_ack(m->slirp, tp, m->m_len);
|
|
406 | 397 |
break; |
407 | 398 |
} |
408 | 399 |
} |
Also available in: Unified diff