bugs in 4.2 and 2.9 tftp user program
satz%srijoyce at sri-unix.UUCP
satz%srijoyce at sri-unix.UUCP
Sat Dec 17 19:57:26 AEST 1983
From: Greg Satz <satz at srijoyce>
The tftp (trivial ftp) program doesn't work. It seems someone didn't
read the fine print when reading the protocol.
Index: ucb/tftp/tftp.c ucb/tftp/main.c 4.2BSD
Description:
The tftp program as distributed doesn't work. When trying to
tftp a file, the first block of data is received and an ACK
reply is sent, but subsequent data is never sent.
Another symptom is getting an error packet from the remote
tftp server saying last packet contained an illegal opcode.
Since netascii format requires all line feeds to be preceeded
by carriage return, something should be done with the carriage
returns.
I have only tested the get command. The only way I can get
a file is to print out the value of sin.sin_port after it has
been reassigned its new value. If I don't print it out, it
acts like the assignment is never done. This seems like a C
compile bug.
Repeat-By:
Run tftp and try to get or put a file. Watch it loop forever
or time-out.
Fix:
The protocol requires that you send either a read request (RRQ)
or write request (WRQ) to a host on port 69 (decimal). All further
packets should be sent to the port that the tftp daemon returns not
to port 69.
Make the following changes to tftp.c:
*** /usr/src/ucb/tftp/tftp.c_ Thu Aug 11 22:44:53 1983
--- /usr/src/ucb/tftp/tftp.c Sat Dec 17 00:10:25 1983
***************
*** 89,94
perror("tftp: recvfrom");
goto abort;
}
if (trace)
tpacket("received", tp, n);
/* should verify packet came from server */
--- 89,95 -----
perror("tftp: recvfrom");
goto abort;
}
+ sin.sin_port = from.sin_port;
if (trace)
tpacket("received", tp, n);
/* should verify packet came from server */
***************
*** 99,105
tp->th_msg);
goto abort;
}
! } while (tp->th_opcode != ACK && block != tp->th_block);
if (block > 0)
amount += size;
block++;
--- 100,106 -----
tp->th_msg);
goto abort;
}
! } while (tp->th_opcode != ACK || block != tp->th_block);
if (block > 0)
amount += size;
block++;
***************
*** 157,162
perror("tftp: recvfrom");
goto abort;
}
if (trace)
tpacket("received", tp, n);
/* should verify client address */
--- 158,164 -----
perror("tftp: recvfrom");
goto abort;
}
+ sin.sin_port = from.sin_port;
if (trace)
tpacket("received", tp, n);
/* should verify client address */
***************
*** 167,173
tp->th_msg);
goto abort;
}
! } while (tp->th_opcode != DATA && block != tp->th_block);
size = write(fd, tp->th_data, n - 4);
if (size < 0) {
nak(errno + 100);
--- 169,175 -----
tp->th_msg);
goto abort;
}
! } while (tp->th_opcode != DATA || block != tp->th_block);
size = write(fd, tp->th_data, n - 4);
if (size < 0) {
nak(errno + 100);
You need to reset the original port (69 decimal) after each
command. These changes to main.c will do that:
*** /usr/src/ucb/tftp/main.c_ Thu Aug 11 22:44:53 1983
--- /usr/src/ucb/tftp/main.c Sat Dec 17 00:13:53 1983
***************
*** 22,27
struct sockaddr_in sin;
int f;
int trace;
int verbose;
int connected;
--- 22,28 -----
struct sockaddr_in sin;
int f;
+ short port;
int trace;
int verbose;
int connected;
***************
*** 149,155
strcpy(hnamebuf, argv[1]);
hostname = hnamebuf;
}
! sin.sin_port = sp->s_port;
if (argc == 3) {
sin.sin_port = atoi(argv[2]);
if (sin.sin_port < 0) {
--- 150,156 -----
strcpy(hnamebuf, argv[1]);
hostname = hnamebuf;
}
! port = sin.sin_port = sp->s_port;
if (argc == 3) {
sin.sin_port = atoi(argv[2]);
if (sin.sin_port < 0) {
***************
*** 157,163
connected = 0;
return;
}
! sin.sin_port = htons((u_short)sin.sin_port);
}
connected = 1;
}
--- 158,164 -----
connected = 0;
return;
}
! port = sin.sin_port = htons((u_short)sin.sin_port);
}
connected = 1;
}
***************
*** 456,461
if (!top)
putchar('\n');
for (;;) {
printf("%s> ", prompt);
if (gets(line) == 0)
continue;
--- 457,463 -----
if (!top)
putchar('\n');
for (;;) {
+ sin.sin_port = port;
printf("%s> ", prompt);
if (gets(line) == 0)
continue;
More information about the Comp.unix.wizards
mailing list