slirp: tftp: Refactor tftp_handle_rrq
Specifically make the filename extraction more readable, and always report errors back to the client. Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
parent
ef2d54d8df
commit
20c24bf24d
49
slirp/tftp.c
49
slirp/tftp.c
@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
struct tftp_session {
|
struct tftp_session {
|
||||||
int in_use;
|
int in_use;
|
||||||
unsigned char filename[TFTP_FILENAME_MAX];
|
char filename[TFTP_FILENAME_MAX];
|
||||||
|
|
||||||
struct in_addr client_ip;
|
struct in_addr client_ip;
|
||||||
u_int16_t client_port;
|
u_int16_t client_port;
|
||||||
@ -273,8 +273,8 @@ static int tftp_send_data(struct tftp_session *spt,
|
|||||||
static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
|
static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
|
||||||
{
|
{
|
||||||
struct tftp_session *spt;
|
struct tftp_session *spt;
|
||||||
int s, k, n;
|
int s, k;
|
||||||
u_int8_t *src, *dst;
|
char *req_fname;
|
||||||
|
|
||||||
s = tftp_session_allocate(tp);
|
s = tftp_session_allocate(tp);
|
||||||
|
|
||||||
@ -290,37 +290,31 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
src = tp->x.tp_buf;
|
/* skip header fields */
|
||||||
dst = spt->filename;
|
k = 0;
|
||||||
n = pktlen - ((uint8_t *)&tp->x.tp_buf[0] - (uint8_t *)tp);
|
pktlen -= ((uint8_t *)&tp->x.tp_buf[0] - (uint8_t *)tp);
|
||||||
|
|
||||||
/* get name */
|
/* get name */
|
||||||
|
req_fname = spt->filename;
|
||||||
|
|
||||||
for (k = 0; k < n; k++) {
|
while (1) {
|
||||||
if (k < TFTP_FILENAME_MAX) {
|
if (k >= TFTP_FILENAME_MAX || k >= pktlen) {
|
||||||
dst[k] = src[k];
|
tftp_send_error(spt, 2, "Access violation", tp);
|
||||||
}
|
|
||||||
else {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
req_fname[k] = (char)tp->x.tp_buf[k];
|
||||||
if (src[k] == '\0') {
|
if (req_fname[k++] == '\0') {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (k >= n) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
k++;
|
|
||||||
|
|
||||||
/* check mode */
|
/* check mode */
|
||||||
if ((n - k) < 6) {
|
if ((pktlen - k) < 6) {
|
||||||
|
tftp_send_error(spt, 2, "Access violation", tp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (memcmp(&src[k], "octet\0", 6) != 0) {
|
if (memcmp(&tp->x.tp_buf[k], "octet\0", 6) != 0) {
|
||||||
tftp_send_error(spt, 4, "Unsupported transfer mode", tp);
|
tftp_send_error(spt, 4, "Unsupported transfer mode", tp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -337,29 +331,28 @@ static void tftp_handle_rrq(struct tftp_t *tp, int pktlen)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* check if the file exists */
|
/* check if the file exists */
|
||||||
|
if (tftp_read_data(spt, 0, NULL, 0) < 0) {
|
||||||
if (tftp_read_data(spt, 0, spt->filename, 0) < 0) {
|
|
||||||
tftp_send_error(spt, 1, "File not found", tp);
|
tftp_send_error(spt, 1, "File not found", tp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src[n - 1] != 0) {
|
if (tp->x.tp_buf[pktlen - 1] != 0) {
|
||||||
tftp_send_error(spt, 2, "Access violation", tp);
|
tftp_send_error(spt, 2, "Access violation", tp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (k < n) {
|
while (k < pktlen) {
|
||||||
const char *key, *value;
|
const char *key, *value;
|
||||||
|
|
||||||
key = (char *)src + k;
|
key = (const char *)&tp->x.tp_buf[k];
|
||||||
k += strlen(key) + 1;
|
k += strlen(key) + 1;
|
||||||
|
|
||||||
if (k >= n) {
|
if (k >= pktlen) {
|
||||||
tftp_send_error(spt, 2, "Access violation", tp);
|
tftp_send_error(spt, 2, "Access violation", tp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
value = (char *)src + k;
|
value = (const char *)&tp->x.tp_buf[k];
|
||||||
k += strlen(value) + 1;
|
k += strlen(value) + 1;
|
||||||
|
|
||||||
if (strcmp(key, "tsize") == 0) {
|
if (strcmp(key, "tsize") == 0) {
|
||||||
|
Loading…
Reference in New Issue
Block a user