Commit 1f697db9c3c22d3768175dbd70e7d5a68638e7b7
1 parent
47d5d01a
Add OACK support to slirp TFTP server, by Anthony Liguori.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2440 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
84 additions
and
0 deletions
slirp/tftp.c
... | ... | @@ -120,6 +120,45 @@ static int tftp_read_data(struct tftp_session *spt, u_int16_t block_nr, |
120 | 120 | return bytes_read; |
121 | 121 | } |
122 | 122 | |
123 | +static int tftp_send_oack(struct tftp_session *spt, | |
124 | + const char *key, uint32_t value, | |
125 | + struct tftp_t *recv_tp) | |
126 | +{ | |
127 | + struct sockaddr_in saddr, daddr; | |
128 | + struct mbuf *m; | |
129 | + struct tftp_t *tp; | |
130 | + int n = 0; | |
131 | + | |
132 | + m = m_get(); | |
133 | + | |
134 | + if (!m) | |
135 | + return -1; | |
136 | + | |
137 | + memset(m->m_data, 0, m->m_size); | |
138 | + | |
139 | + m->m_data += if_maxlinkhdr; | |
140 | + tp = (void *)m->m_data; | |
141 | + m->m_data += sizeof(struct udpiphdr); | |
142 | + | |
143 | + tp->tp_op = htons(TFTP_OACK); | |
144 | + n += sprintf(tp->x.tp_buf + n, "%s", key) + 1; | |
145 | + n += sprintf(tp->x.tp_buf + n, "%u", value) + 1; | |
146 | + | |
147 | + saddr.sin_addr = recv_tp->ip.ip_dst; | |
148 | + saddr.sin_port = recv_tp->udp.uh_dport; | |
149 | + | |
150 | + daddr.sin_addr = spt->client_ip; | |
151 | + daddr.sin_port = spt->client_port; | |
152 | + | |
153 | + m->m_len = sizeof(struct tftp_t) - 514 + n - | |
154 | + sizeof(struct ip) - sizeof(struct udphdr); | |
155 | + udp_output2(NULL, m, &saddr, &daddr, IPTOS_LOWDELAY); | |
156 | + | |
157 | + return 0; | |
158 | +} | |
159 | + | |
160 | + | |
161 | + | |
123 | 162 | static int tftp_send_error(struct tftp_session *spt, |
124 | 163 | u_int16_t errorcode, const char *msg, |
125 | 164 | struct tftp_t *recv_tp) |
... | ... | @@ -273,6 +312,8 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen) |
273 | 312 | return; |
274 | 313 | } |
275 | 314 | |
315 | + k += 6; /* skipping octet */ | |
316 | + | |
276 | 317 | /* do sanity checks on the filename */ |
277 | 318 | |
278 | 319 | if ((spt->filename[0] != '/') |
... | ... | @@ -297,6 +338,48 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen) |
297 | 338 | return; |
298 | 339 | } |
299 | 340 | |
341 | + if (src[n - 1] != 0) { | |
342 | + tftp_send_error(spt, 2, "Access violation", tp); | |
343 | + return; | |
344 | + } | |
345 | + | |
346 | + while (k < n) { | |
347 | + const char *key, *value; | |
348 | + | |
349 | + key = src + k; | |
350 | + k += strlen(key) + 1; | |
351 | + | |
352 | + if (k >= n) { | |
353 | + tftp_send_error(spt, 2, "Access violation", tp); | |
354 | + return; | |
355 | + } | |
356 | + | |
357 | + value = src + k; | |
358 | + k += strlen(value) + 1; | |
359 | + | |
360 | + if (strcmp(key, "tsize") == 0) { | |
361 | + int tsize = atoi(value); | |
362 | + struct stat stat_p; | |
363 | + | |
364 | + if (tsize == 0 && tftp_prefix) { | |
365 | + char buffer[1024]; | |
366 | + int len; | |
367 | + | |
368 | + len = snprintf(buffer, sizeof(buffer), "%s/%s", | |
369 | + tftp_prefix, spt->filename); | |
370 | + | |
371 | + if (stat(buffer, &stat_p) == 0) | |
372 | + tsize = stat_p.st_size; | |
373 | + else { | |
374 | + tftp_send_error(spt, 1, "File not found", tp); | |
375 | + return; | |
376 | + } | |
377 | + } | |
378 | + | |
379 | + tftp_send_oack(spt, "tsize", tsize, tp); | |
380 | + } | |
381 | + } | |
382 | + | |
300 | 383 | tftp_send_data(spt, 1, tp); |
301 | 384 | } |
302 | 385 | ... | ... |