slirp: support dynamic block size for TFTP transfers

The blocksize option is defined in RFC 1783 and RFC 2348.
We now support block sizes between 1 and 1428 bytes, instead of 512 only.

Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
This commit is contained in:
Hervé Poussineau 2016-11-21 20:45:49 +01:00 committed by Samuel Thibault
parent 893dcdbfa9
commit 9443598d7e
2 changed files with 19 additions and 15 deletions

View File

@ -72,6 +72,7 @@ static int tftp_session_allocate(Slirp *slirp, struct sockaddr_storage *srcsas,
memset(spt, 0, sizeof(*spt));
spt->client_addr = *srcsas;
spt->fd = -1;
spt->block_size = 512;
spt->client_port = tp->udp.uh_sport;
spt->slirp = slirp;
@ -115,7 +116,7 @@ static int tftp_read_data(struct tftp_session *spt, uint32_t block_nr,
}
if (len) {
lseek(spt->fd, block_nr * 512, SEEK_SET);
lseek(spt->fd, block_nr * spt->block_size, SEEK_SET);
bytes_read = read(spt->fd, buf, len);
}
@ -189,7 +190,8 @@ static int tftp_send_oack(struct tftp_session *spt,
values[i]) + 1;
}
m->m_len = sizeof(struct tftp_t) - 514 + n - sizeof(struct udphdr);
m->m_len = sizeof(struct tftp_t) - (TFTP_BLOCKSIZE_MAX + 2) + n
- sizeof(struct udphdr);
tftp_udp_output(spt, m, recv_tp);
return 0;
@ -214,7 +216,7 @@ static void tftp_send_error(struct tftp_session *spt,
tp->x.tp_error.tp_error_code = htons(errorcode);
pstrcpy((char *)tp->x.tp_error.tp_msg, sizeof(tp->x.tp_error.tp_msg), msg);
m->m_len = sizeof(struct tftp_t) - 514 + 3 + strlen(msg)
m->m_len = sizeof(struct tftp_t) - (TFTP_BLOCKSIZE_MAX + 2) + 3 + strlen(msg)
- sizeof(struct udphdr);
tftp_udp_output(spt, m, recv_tp);
@ -240,7 +242,8 @@ static void tftp_send_next_block(struct tftp_session *spt,
tp->tp_op = htons(TFTP_DATA);
tp->x.tp_data.tp_block_nr = htons((spt->block_nr + 1) & 0xffff);
nobytes = tftp_read_data(spt, spt->block_nr, tp->x.tp_data.tp_buf, 512);
nobytes = tftp_read_data(spt, spt->block_nr, tp->x.tp_data.tp_buf,
spt->block_size);
if (nobytes < 0) {
m_free(m);
@ -252,10 +255,11 @@ static void tftp_send_next_block(struct tftp_session *spt,
return;
}
m->m_len = sizeof(struct tftp_t) - (512 - nobytes) - sizeof(struct udphdr);
m->m_len = sizeof(struct tftp_t) - (TFTP_BLOCKSIZE_MAX - nobytes)
- sizeof(struct udphdr);
tftp_udp_output(spt, m, recv_tp);
if (nobytes == 512) {
if (nobytes == spt->block_size) {
tftp_session_update(spt);
}
else {
@ -385,13 +389,11 @@ static void tftp_handle_rrq(Slirp *slirp, struct sockaddr_storage *srcsas,
} else if (strcasecmp(key, "blksize") == 0) {
int blksize = atoi(value);
/* If blksize option is bigger than what we will
* emit, accept the option with our packet size.
* Otherwise, simply do as we didn't see the option.
*/
if (blksize >= 512) {
/* Accept blksize up to our maximum size */
if (blksize > 0) {
spt->block_size = MIN(blksize, TFTP_BLOCKSIZE_MAX);
option_name[nb_options] = "blksize";
option_value[nb_options] = 512;
option_value[nb_options] = spt->block_size;
nb_options++;
}
}

View File

@ -15,6 +15,7 @@
#define TFTP_OACK 6
#define TFTP_FILENAME_MAX 512
#define TFTP_BLOCKSIZE_MAX 1428
struct tftp_t {
struct udphdr udp;
@ -22,13 +23,13 @@ struct tftp_t {
union {
struct {
uint16_t tp_block_nr;
uint8_t tp_buf[512];
uint8_t tp_buf[TFTP_BLOCKSIZE_MAX];
} tp_data;
struct {
uint16_t tp_error_code;
uint8_t tp_msg[512];
uint8_t tp_msg[TFTP_BLOCKSIZE_MAX];
} tp_error;
char tp_buf[512 + 2];
char tp_buf[TFTP_BLOCKSIZE_MAX + 2];
} x;
} __attribute__((packed));
@ -36,6 +37,7 @@ struct tftp_session {
Slirp *slirp;
char *filename;
int fd;
uint16_t block_size;
struct sockaddr_storage client_addr;
uint16_t client_port;