[syslinux] truncated files on write with tftpd-hpa

Alan Sundell asundell+syslinux at fas.harvard.edu
Fri May 2 14:00:08 PDT 2003


On Thu, May 01, 2003 at 11:31:35PM -0700, H. Peter Anvin wrote:
> This is bizarre.  Do you have an strace -f -tt ?

Not at the moment.  I don't think DigitalUNIX has that kind of strace,
but I'll see what I can do (unfortunately, testing this involves me
taking one of the network guys hostage to upload a switch
configuration again and again).  That will have to be a next week sort
of thing.


In the meantime, I'm basing my assertions about the code flow on the
syslog messages and tcpdump.  I think if you take a look at things
again, you'll see what I'm talking about.

For instance, the syslog from the second child:

| May  1 16:23:10 [server] tftpd[14255]: WRQ from [client] filename switch.config remapped to /switch.config
| May  1 16:23:10 [server] tftpd[14255]: tftpd: read: Connection refused

Based just on the syslog formats, you can tell that the first message
there must come from line 764, in tftp(), after rewrite_access() and
before validate_access().  The second line must come from line 1290 in
tftp_recvfile(), since the only other occurrence is on line 1172 in
tftp_sendfile().


The message "Connection refused" is, I think, a little misleading,
since it has nothing to do with connect(), but seems rather to be a
response to the ICMP packet from the client sent after the ACK, but I
think that's just semantic weirdness because this is UDP.

Based on what I've seen here, I don't think connect() really does
anything in UDP except establish the endpoints for future send()s and
recv()s.  In other words, since it doesn't send any packets, it can't
possibly return ECONNREFUSED.  That would seem to be supported by the
language of the manpage:

| The connect() function performs a different action for each of the
| following types of initiating sockets:
|
|   o  If the initiating socket is SOCK_DGRAM, the connect() function
|      establishes the peer address.  The peer address identifies the
|      socket where all datagrams are sent on subsequent send()
|      functions. It also identifies the socket from where datagrams
|      can be received; datagrams from other peer addresses are not
|      delivered.
|
|      No connections are made by this connect function.

The manpage on Linux implies similar behavior, if the manpages are to
be trusted.


AFAICT, the packets corresponding to the second child are only these
three:
| 17:23:08.532809 [client].1036 > [server].69: 29 WRQ "switch.config"
| 17:23:10.651003 [server].1335 > [client].1036: udp 4
| 17:23:10.656862 [client] > [server]: icmp: [client] udp port 1036 unreachable

The first packet results in the return of myrecvfrom() on line 546.
The second is a TFTP ACK packet, according to tethereal, which could
only have been sent by the send() on line 1281.  The third must
somehow later trigger the error message, so 

If all the above is true, then the system must be storing state on the
socket from when it receives the ICMP message, and letting the
application know the next time it accesses the socket, which would be
in the recv() called from the recv_time() line 1288.


Does that make some sense?  It seems to me like it fits with the data
we see.

--Alan


More information about the Syslinux mailing list