Commit 1f697db9c3c22d3768175dbd70e7d5a68638e7b7

Authored by ths
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  
... ...
slirp/tftp.h
... ... @@ -9,6 +9,7 @@
9 9 #define TFTP_DATA 3
10 10 #define TFTP_ACK 4
11 11 #define TFTP_ERROR 5
  12 +#define TFTP_OACK 6
12 13  
13 14 #define TFTP_FILENAME_MAX 512
14 15  
... ...