Documented the purpose of the two timeout fields in
[people/xl0/gpxe.git] / src / interface / pxe / pxe_tftp.c
1 /** @file
2  *
3  * PXE TFTP API
4  *
5  */
6
7 /*
8  * Copyright (C) 2004 Michael Brown <mbrown@fensystems.co.uk>.
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License as
12  * published by the Free Software Foundation; either version 2 of the
13  * License, or any later version.
14  *
15  * This program is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24
25 #include "pxe.h"
26
27 /**
28  * TFTP OPEN
29  *
30  * @v tftp_open                         Pointer to a struct s_PXENV_TFTP_OPEN
31  * @v s_PXENV_TFTP_OPEN::ServerIPAddress TFTP server IP address
32  * @v s_PXENV_TFTP_OPEN::GatewayIPAddress Relay agent IP address, or 0.0.0.0
33  * @v s_PXENV_TFTP_OPEN::FileName       Name of file to open
34  * @v s_PXENV_TFTP_OPEN::TFTPPort       TFTP server UDP port
35  * @v s_PXENV_TFTP_OPEN::PacketSize     TFTP blksize option to request
36  * @ret #PXENV_EXIT_SUCCESS             File was opened
37  * @ret #PXENV_EXIT_FAILURE             File was not opened
38  * @ret s_PXENV_TFTP_OPEN::Status       PXE status code
39  * @ret s_PXENV_TFTP_OPEN::PacketSize   Negotiated blksize
40  * @err #PXENV_STATUS_TFTP_INVALID_PACKET_SIZE Requested blksize too small
41  *
42  * Opens a TFTP connection for downloading a file a block at a time
43  * using pxenv_tftp_read().
44  *
45  * If s_PXENV_TFTP_OPEN::GatewayIPAddress is 0.0.0.0, normal IP
46  * routing will take place.  See the relevant
47  * @ref pxe_routing "implementation note" for more details.
48  *
49  * The blksize negotiated with the TFTP server will be returned in
50  * s_PXENV_TFTP_OPEN::PacketSize, and will be the size of data blocks
51  * returned by subsequent calls to pxenv_tftp_read().  The TFTP server
52  * may negotiate a smaller blksize than the caller requested.
53  *
54  * Some TFTP servers do not support TFTP options, and will therefore
55  * not be able to use anything other than a fixed 512-byte blksize.
56  * The PXE specification version 2.1 requires that the caller must
57  * pass in s_PXENV_TFTP_OPEN::PacketSize with a value of 512 or
58  * greater.
59  *
60  * You can only have one TFTP connection open at a time, because the
61  * PXE API requires the PXE stack to keep state (e.g. local and remote
62  * port numbers, data block index) about the open TFTP connection,
63  * rather than letting the caller do so.
64  *
65  * It is unclear precisely what constitutes a "TFTP open" operation.
66  * Clearly, we must send the TFTP open request to the server.  Since
67  * we must know whether or not the open succeeded, we must wait for
68  * the first reply packet from the TFTP server.  If the TFTP server
69  * supports options, the first reply packet will be an OACK; otherwise
70  * it will be a DATA packet.  In other words, we may only get to
71  * discover whether or not the open succeeded when we receive the
72  * first block of data.  However, the pxenv_tftp_open() API provides
73  * no way for us to return this block of data at this time.  See the
74  * relevant @ref pxe_note_tftp "implementation note" for Etherboot's
75  * solution to this problem.
76  *
77  * 
78  * @note If you pass in a value less than 512 for
79  * s_PXENV_TFTP_OPEN::PacketSize, Etherboot will attempt to negotiate
80  * this blksize with the TFTP server, even though such a value is not
81  * permitted according to the PXE specification.  If the TFTP server
82  * ends up dictating a blksize larger than the value requested by the
83  * caller (which is very probable in the case of a requested blksize
84  * less than 512), then Etherboot will return the error
85  * #PXENV_STATUS_TFTP_INVALID_PACKET_SIZE.
86  *
87  * @note According to the PXE specification version 2.1, this call
88  * "opens a file for reading/writing", though how writing is to be
89  * achieved without the existence of an API call %pxenv_tftp_write()
90  * is not made clear.
91  *
92  * Status: working
93  */
94 PXENV_EXIT_t pxenv_tftp_open ( struct s_PXENV_TFTP_OPEN *tftp_open ) {
95         struct sockaddr_in tftp_server;
96         struct tftpreq_info_t request;
97         struct tftpblk_info_t block;
98
99         DBG ( "PXENV_TFTP_OPEN" );
100         ENSURE_READY ( tftp_open );
101
102         /* Set server address and port */
103         tftp_server.sin_addr.s_addr = tftp_open->ServerIPAddress
104                 ? tftp_open->ServerIPAddress
105                 : arptable[ARP_SERVER].ipaddr.s_addr;
106         tftp_server.sin_port = ntohs ( tftp_open->TFTPPort );
107 #ifdef WORK_AROUND_BPBATCH_BUG        
108         /* Force use of port 69; BpBatch tries to use port 4 for some         
109         * bizarre reason.         */        
110         tftp_server.sin_port = TFTP_PORT;
111 #endif
112         /* Ignore gateway address; we can route properly */
113         /* Fill in request structure */
114         request.server = &tftp_server;
115         request.name = tftp_open->FileName;
116         request.blksize = tftp_open->PacketSize;
117         DBG ( " %@:%d/%s (%d)", tftp_open->ServerIPAddress,
118               tftp_open->TFTPPort, request.name, request.blksize );
119         if ( !request.blksize ) request.blksize = TFTP_DEFAULTSIZE_PACKET;
120         /* Make request and get first packet */
121         if ( !tftp_block ( &request, &block ) ) {
122                 tftp_open->Status = PXENV_STATUS_TFTP_FILE_NOT_FOUND;
123                 return PXENV_EXIT_FAILURE;
124         }
125         /* Fill in PacketSize */
126         tftp_open->PacketSize = request.blksize;
127         /* Store first block for later retrieval by TFTP_READ */
128         pxe_stack->tftpdata.magic_cookie = PXE_TFTP_MAGIC_COOKIE;
129         pxe_stack->tftpdata.len = block.len;
130         pxe_stack->tftpdata.eof = block.eof;
131         memcpy ( pxe_stack->tftpdata.data, block.data, block.len );
132
133         tftp_open->Status = PXENV_STATUS_SUCCESS;
134         return PXENV_EXIT_SUCCESS;
135 }
136
137 /* PXENV_TFTP_CLOSE
138  *
139  * Status: working
140  */
141 PXENV_EXIT_t pxenv_tftp_close ( struct s_PXENV_TFTP_CLOSE *tftp_close ) {
142         DBG ( "PXENV_TFTP_CLOSE" );
143         ENSURE_READY ( tftp_close );
144         tftp_close->Status = PXENV_STATUS_SUCCESS;
145         return PXENV_EXIT_SUCCESS;
146 }
147
148 /* PXENV_TFTP_READ
149  *
150  * Status: working
151  */
152 PXENV_EXIT_t pxenv_tftp_read ( struct s_PXENV_TFTP_READ *tftp_read ) {
153         struct tftpblk_info_t block;
154
155         DBG ( "PXENV_TFTP_READ" );
156         ENSURE_READY ( tftp_read );
157
158         /* Do we have a block pending */
159         if ( pxe_stack->tftpdata.magic_cookie == PXE_TFTP_MAGIC_COOKIE ) {
160                 block.data = pxe_stack->tftpdata.data;
161                 block.len = pxe_stack->tftpdata.len;
162                 block.eof = pxe_stack->tftpdata.eof;
163                 block.block = 1; /* Will be the first block */
164                 pxe_stack->tftpdata.magic_cookie = 0;
165         } else {
166                 if ( !tftp_block ( NULL, &block ) ) {
167                         tftp_read->Status = PXENV_STATUS_TFTP_FILE_NOT_FOUND;
168                         return PXENV_EXIT_FAILURE;
169                 }
170         }
171
172         /* Return data */
173         tftp_read->PacketNumber = block.block;
174         tftp_read->BufferSize = block.len;
175         memcpy ( SEGOFF16_TO_PTR(tftp_read->Buffer), block.data, block.len );
176         DBG ( " %d to %hx:%hx", block.len, tftp_read->Buffer.segment,
177               tftp_read->Buffer.offset );
178  
179         tftp_read->Status = PXENV_STATUS_SUCCESS;
180         return PXENV_EXIT_SUCCESS;
181 }
182
183 /* PXENV_TFTP_READ_FILE
184  *
185  * Status: working
186  */
187
188 int pxe_tftp_read_block ( unsigned char *data, unsigned int block __unused,
189                           unsigned int len, int eof ) {
190         if ( pxe_stack->readfile.buffer ) {
191                 if ( pxe_stack->readfile.offset + len >=
192                      pxe_stack->readfile.bufferlen ) return -1;
193                 memcpy ( pxe_stack->readfile.buffer +
194                          pxe_stack->readfile.offset, data, len );
195         }
196         pxe_stack->readfile.offset += len;
197         return eof ? 0 : 1;
198 }
199
200 PXENV_EXIT_t pxenv_tftp_read_file ( struct s_PXENV_TFTP_READ_FILE
201                                     *tftp_read_file ) {
202         struct sockaddr_in tftp_server;
203         int rc;
204
205         DBG ( "PXENV_TFTP_READ_FILE %s to [%x,%x)", tftp_read_file->FileName,
206               tftp_read_file->Buffer,
207               tftp_read_file->Buffer + tftp_read_file->BufferSize );
208         ENSURE_READY ( tftp_read_file );
209
210         /* inserted by Klaus Wittemeier */
211         /* KERNEL_BUF stores the name of the last required file */
212         /* This is a fix to make Microsoft Remote Install Services work (RIS) */
213         memcpy(KERNEL_BUF, tftp_read_file->FileName, sizeof(KERNEL_BUF));
214         /* end of insertion */
215
216         /* Set server address and port */
217         tftp_server.sin_addr.s_addr = tftp_read_file->ServerIPAddress
218                 ? tftp_read_file->ServerIPAddress
219                 : arptable[ARP_SERVER].ipaddr.s_addr;
220         tftp_server.sin_port = ntohs ( tftp_read_file->TFTPSrvPort );
221
222         pxe_stack->readfile.buffer = phys_to_virt ( tftp_read_file->Buffer );
223         pxe_stack->readfile.bufferlen = tftp_read_file->BufferSize;
224         pxe_stack->readfile.offset = 0;
225
226         rc = tftp ( NULL, &tftp_server, tftp_read_file->FileName,
227                     pxe_tftp_read_block );
228         if ( rc ) {
229                 tftp_read_file->Status = PXENV_STATUS_FAILURE;
230                 return PXENV_EXIT_FAILURE;
231         }
232         tftp_read_file->Status = PXENV_STATUS_SUCCESS;
233         return PXENV_EXIT_SUCCESS;
234 }
235
236 /* PXENV_TFTP_GET_FSIZE
237  *
238  * Status: working, though ugly (we actually read the whole file,
239  * because it's too ugly to make Etherboot request the tsize option
240  * and hand it to us).
241  */
242 PXENV_EXIT_t pxenv_tftp_get_fsize ( struct s_PXENV_TFTP_GET_FSIZE
243                                     *tftp_get_fsize ) {
244         int rc;
245
246         DBG ( "PXENV_TFTP_GET_FSIZE" );
247         ENSURE_READY ( tftp_get_fsize );
248
249         pxe_stack->readfile.buffer = NULL;
250         pxe_stack->readfile.bufferlen = 0;
251         pxe_stack->readfile.offset = 0;
252
253 #warning "Rewrite pxenv_tftp_get_fsize, please"
254         if ( rc ) {
255                 tftp_get_fsize->FileSize = 0;
256                 tftp_get_fsize->Status = PXENV_STATUS_FAILURE;
257                 return PXENV_EXIT_FAILURE;
258         }
259         tftp_get_fsize->FileSize = pxe_stack->readfile.offset;
260         tftp_get_fsize->Status = PXENV_STATUS_SUCCESS;
261         return PXENV_EXIT_SUCCESS;
262 }
263
264 /** @page pxe_notes Etherboot PXE implementation notes
265
266 @section pxe_note_tftp Welding together the TFTP protocol and the PXE TFTP API
267
268 The PXE TFTP API is fundamentally poorly designed; the TFTP protocol
269 simply does not map well into "open file", "read file block", "close
270 file" operations.  The problem is the unreliable nature of UDP
271 transmissions and the lock-step mechanism employed by TFTP to
272 guarantee file transfer.  The lock-step mechanism requires that if we
273 time out waiting for a packet to arrive, we must trigger its
274 retransmission by retransmitting our own previously transmitted
275 packet.
276
277 For example, suppose that pxenv_tftp_read() is called to read the
278 first data block of a file from a server that does not support TFTP
279 options, and that no data block is received within the timeout period.
280 In order to trigger the retransmission of this data block,
281 pxenv_tftp_read() must retransmit the TFTP open request.  However, the
282 information used to build the TFTP open request is not available at
283 this time; it was provided only to the pxenv_tftp_open() call.  Even
284 if we were able to retransmit a TFTP open request, we would have to
285 allocate a new local port number (and be prepared for data to arrive
286 from a new remote port number) in order to avoid violating the TFTP
287 protocol specification.
288
289 The question of when to transmit the ACK packets is also awkward.  At
290 a first glance, it would seem to be fairly simple: acknowledge a
291 packet immediately after receiving it.  However, since the ACK packet
292 may itself be lost, the next call to pxenv_tftp_read() must be
293 prepared to retransmit the acknowledgement.
294
295 Another problem to consider is that the pxenv_tftp_open() API call
296 must return an indication of whether or not the TFTP open request
297 succeeded.  In the case of a TFTP server that doesn't support TFTP
298 options, the only indication of a successful open is the reception of
299 the first data block.  However, the pxenv_tftp_open() API provides no
300 way to return this data block at this time.
301
302 At least some PXE stacks (e.g. NILO) solve this problem by violating
303 the TFTP protocol and never bothering with retransmissions, relying on
304 the TFTP server to retransmit when it times out waiting for an ACK.
305 This approach is dubious at best; if, for example, the initial TFTP
306 open request is lost then NILO will believe that it has opened the
307 file and will eventually time out and give up while waiting for the
308 first packet to arrive.
309
310 The only viable solution seems to be to allocate a buffer for the
311 storage of the first data packet returned by the TFTP server, since we
312 may receive this packet during the pxenv_tftp_open() call but have to
313 return it from the subsequent pxenv_tftp_read() call.  This buffer
314 must be statically allocated and must be dedicated to providing a
315 temporary home for TFTP packets.  There is nothing in the PXE
316 specification that prevents a caller from calling
317 e.g. pxenv_undi_transmit() between calls to the TFTP API, so we cannot
318 use the normal transmit/receive buffer for this purpose.
319
320 Having paid the storage penalty for this buffer, we can then gain some
321 simplicity by exploiting it in full.  There is at least one
322 circumstance (pxenv_tftp_open() called to open a file on a server that
323 does not support TFTP options) in which we will have to enter
324 pxenv_tftp_read() knowing that our previous transmission (the open
325 request, in this situation) has already been acknowledged.
326 Implementation of pxenv_tftp_read() can be made simpler by making this
327 condition an invariant.  Specifically, on each call to
328 pxenv_tftp_read(), we shall ensure that the following are true:
329
330   - Our previous transmission has already been acknowledged.  We
331     therefore do not need to keep state about our previous
332     transmission.
333
334   - The next packet to read is already in a buffer in memory.
335
336 In order to maintain these two conditions, pxenv_tftp_read() must do
337 the following:
338
339   - Copy the data packet from our buffer to the caller's buffer.
340
341   - Acknowledge the data packet that we have just copied.  This will
342     trigger transmission of the next packet from the server.
343
344   - Retransmit this acknowledgement packet until the next packet
345     arrives.
346
347   - Copy the packet into our internal buffer, ready for the next call
348     to pxenv_tftp_read().
349
350 It can be verified that this preserves the invariant condition, and it
351 is clear that the resulting implementation of pxenv_tftp_read() can be
352 relatively simple.  (For the special case of the last data packet,
353 pxenv_tftp_read() should return immediately after sending a single
354 acknowledgement packet.)
355
356 In order to set up this invariant condition for the first call to
357 pxenv_tftp_read(), pxenv_tftp_open() must do the following:
358
359   - Construct and transmit the TFTP open request.
360
361   - Retransmit the TFTP open request (using a new local port number as
362     necessary) until a response (DATA, OACK, or ERROR) is received.
363
364   - If the response is an OACK, acknowledge the OACK and retransmit
365     the acknowledgement until the first DATA packet arrives.
366
367   - If we have a DATA packet, store it in a buffer ready for the first
368     call to pxenv_tftp_read().
369
370 This approach has the advantage of being fully compliant with both
371 RFC1350 (TFTP) and RFC2347 (TFTP options).  It avoids unnecessary
372 retransmissions.  The cost is approximately 1500 bytes of
373 uninitialised storage.  Since there is demonstrably no way to avoid
374 paying this cost without either violating the protocol specifications
375 or introducing unnecessary retransmissions, we deem this to be a cost
376 worth paying.
377
378 A small performance gain may be obtained by adding a single extra
379 "send ACK" in both pxenv_tftp_open() and pxenv_tftp_read() immediately
380 after receiving the DATA packet and copying it into the internal
381 buffer.   The sequence of events for pxenv_tftp_read() then becomes:
382
383   - Copy the data packet from our buffer to the caller's buffer.
384
385   - If this was the last data packet, return immediately.
386
387   - Check to see if a TFTP data packet is waiting.  If not, send an
388     ACK for the data packet that we have just copied, and retransmit
389     this ACK until the next data packet arrives.
390
391   - Copy the packet into our internal buffer, ready for the next call
392     to pxenv_tftp_read().
393
394   - Send a single ACK for this data packet.
395
396 Sending the ACK at this point allows the server to transmit the next
397 data block while our caller is processing the current packet.  If this
398 ACK is lost, or the DATA packet it triggers is lost or is consumed by
399 something other than pxenv_tftp_read() (e.g. by calls to
400 pxenv_undi_isr()), then the next call to pxenv_tftp_read() will not
401 find a TFTP data packet waiting and will retransmit the ACK anyway.
402
403 Note to future API designers at Intel: try to understand the
404 underlying network protocol first!
405
406 */