Don't choke on duplicate OACK packets.
[people/xl0/gpxe.git] / src / proto / tftpcore.c
1 #include "tftp.h"
2 #include "tcp.h" /* for struct tcphdr */
3 #include "errno.h"
4 #include "etherboot.h"
5 #include "tftpcore.h"
6
7 /** @file */
8
9 /**
10  * await_reply() filter for TFTP packets
11  *
12  * @v ptr                       Pointer to a struct tftp_state
13  * @v tftp_state::server::sin_addr TFTP server IP address
14  * @v tftp_state::client::sin_addr Client multicast IP address, or 0.0.0.0
15  * @v tftp_state::client::sin_port Client UDP port
16  * @v ip                        IP header
17  * @v udp                       UDP header
18  * @ret True                    This is our TFTP packet
19  * @ret False                   This is not one of our TFTP packets
20  *
21  * Wait for a TFTP packet that is part of the current connection
22  * (i.e. comes from the TFTP server, has the correct destination port,
23  * and is addressed either to our IP address or to our multicast
24  * listening address).
25  *
26  * Use await_tftp() in code such as
27  *
28  * @code
29  *
30  * if ( await_reply ( await_tftp, 0, &tftp_state, timeout ) ) {
31  *      ...
32  * }
33  *
34  * @endcode
35  */
36 static int await_tftp ( int ival __unused, void *ptr,
37                         unsigned short ptype __unused, struct iphdr *ip,
38                         struct udphdr *udp, struct tcphdr *tcp __unused ) {
39         struct tftp_state *state = ptr;
40
41         /* Must have valid UDP (and, therefore, also IP) headers */
42         if ( ! udp ) {
43                 DBG2 ( "TFTPCORE: not UDP\n" );
44                 return 0;
45         }
46         /* Packet must come from the TFTP server */
47         if ( ip->src.s_addr != state->server.sin_addr.s_addr ) {
48                 DBG2 ( "TFTPCORE: from %@, not from TFTP server %@\n",
49                        ip->src.s_addr, state->server.sin_addr.s_addr );
50                 return 0;
51         }
52         /* Packet must be addressed to the correct UDP port */
53         if ( ntohs ( udp->dest ) != state->client.sin_port ) {
54                 DBG2 ( "TFTPCORE: to UDP port %d, not to TFTP port %d\n",
55                        ntohs ( udp->dest ), state->client.sin_port );
56                 return 0;
57         }
58         /* Packet must be addressed to us, or to our multicast
59          * listening address (if we have one).
60          */
61         if ( ! ( ( ip->dest.s_addr == arptable[ARP_CLIENT].ipaddr.s_addr ) ||
62                  ( ( state->client.sin_addr.s_addr ) && 
63                    ( ip->dest.s_addr == state->client.sin_addr.s_addr ) ) ) ) {
64                 DBG2 ( "TFTPCORE: to %@, not to %@ (or %@)\n",
65                        ip->dest.s_addr, arptable[ARP_CLIENT].ipaddr.s_addr,
66                        state->client.sin_addr.s_addr );
67                 return 0;
68         }
69         return 1;
70 }
71
72 /**
73  * Retrieve a TFTP packet
74  *
75  * @v state                     TFTP transfer state
76  * @v tftp_state::server::sin_addr TFTP server IP address
77  * @v tftp_state::client::sin_addr Client multicast IP address, or 0.0.0.0
78  * @v tftp_state::client::sin_port Client UDP port
79  * @v timeout                   Time to wait for a response
80  * @ret True                    Received a non-error response
81  * @ret False                   Received error response / no response
82  * @ret *reply                  The server's response, if any
83  * @err #PXENV_STATUS_TFTP_READ_TIMEOUT No response received in time
84  * @err other                   As set by tftp_set_errno()
85  *
86  * Retrieve the next packet sent by the TFTP server, if any is sent
87  * within the specified timeout period.  The packet is returned via
88  * #reply.  If no packet is received within the timeout period, a NULL
89  * value will be stored in #reply.
90  *
91  * If the response from the server is a TFTP ERROR packet, tftp_get()
92  * will return False and #errno will be set accordingly.
93  *
94  * You can differentiate between "received no response" and "received
95  * an error response" by checking #reply; if #reply is NULL then no
96  * response was received.
97  */
98 int tftp_get ( struct tftp_state *state, long timeout,
99                union tftp_any **reply ) {
100
101         *reply = NULL;
102
103         if ( ! await_reply ( await_tftp, 0, state, timeout ) ) {
104                 errno = PXENV_STATUS_TFTP_READ_TIMEOUT;
105                 return 0;
106         }
107
108         *reply = ( union tftp_any * ) &nic.packet[ETH_HLEN];
109         DBG ( "TFTPCORE: got reply (type %d)\n",
110               ntohs ( (*reply)->common.opcode ) );
111         if ( ntohs ( (*reply)->common.opcode ) == TFTP_ERROR ){
112                 tftp_set_errno ( &(*reply)->error );
113                 return 0;
114         }
115         return 1;
116 }
117
118 /**
119  * Issue a TFTP open request (RRQ)
120  *
121  * @v state                             TFTP transfer state
122  * @v tftp_state::server::sin_addr      TFTP server IP address
123  * @v tftp_state::server::sin_port      TFTP server UDP port, or 0
124  * @v tftp_state::client::sin_addr      Client multicast IP address, or 0.0.0.0
125  * @v tftp_state::client::sin_port      Client UDP port, or 0
126  * @v tftp_state::blksize               Requested blksize, or 0
127  * @v filename                          File name
128  * @ret True                            Received a non-error response
129  * @ret False                           Received error response / no response
130  * @ret tftp_state::server::sin_port    TFTP server UDP port
131  * @ret tftp_state::client::sin_port    Client UDP port
132  * @ret tftp_state::blksize             Always #TFTP_DEFAULT_BLKSIZE
133  * @ret *reply                          The server's response, if any
134  * @err #PXENV_STATUS_TFTP_OPEN_TIMEOUT TFTP open timed out
135  * @err other                           As returned by udp_transmit()
136  * @err other                           As set by tftp_set_errno()
137  *
138  * Send a TFTP/TFTM/MTFTP RRQ (read request) to a TFTP server, and
139  * return the server's reply (which may be an OACK, DATA or ERROR
140  * packet).  The server's reply will not be acknowledged, or processed
141  * in any way.
142  *
143  * If tftp_state::server::sin_port is 0, the standard TFTP server port
144  * (#TFTP_PORT) will be used.
145  *
146  * If tftp_state::client::sin_addr is not 0.0.0.0, it will be used as
147  * a multicast listening address for replies from the TFTP server.
148  *
149  * If tftp_state::client::sin_port is 0, the standard mechanism of
150  * using a new, unique port number for each TFTP request will be used.
151  * 
152  * For the various different types of TFTP server, you should treat
153  * tftp_state::client as follows:
154  *
155  *   - Standard TFTP server: set tftp_state::client::sin_addr to
156  *     0.0.0.0 and tftp_state::client::sin_port to 0.  tftp_open()
157  *     will set tftp_state::client::sin_port to the assigned local UDP
158  *     port.
159  *
160  *   - TFTM server: set tftp_state::client::sin_addr to 0.0.0.0 and
161  *     tftp_state::client::sin_port to 0.  tftp_open() will set
162  *     tftp_state::client::sin_port to the assigned local UDP port.
163  *     (Your call to tftp_process_opts() will then overwrite both
164  *     tftp_state::client::sin_addr and tftp_state::client::sin_port
165  *     with the values return in the OACK packet.)
166  *
167  *   - MTFTP server: set tftp_state::client::sin_addr to the client
168  *     multicast address and tftp_state::client::sin_port to the
169  *     client multicast port (both of which must be previously known,
170  *     e.g. provided by a DHCP server).  tftp_open() will not alter
171  *     these values.
172  *
173  * If tftp_state::blksize is 0, the maximum blocksize
174  * (#TFTP_MAX_BLKSIZE) will be requested.
175  *
176  * On exit, tftp_state::blksize will always contain
177  * #TFTP_DEFAULT_BLKSIZE, since this is the blocksize value that must
178  * be assumed until the OACK packet is processed (by a subsequent call
179  * to tftp_process_opts()).
180  *
181  * tftp_state::server::sin_port will be set to the UDP port from which
182  * the server's response originated.  This may or may not be the port
183  * to which the open request was sent.
184  *
185  * The options "blksize", "tsize" and "multicast" will always be
186  * appended to a TFTP open request.  Servers that do not understand
187  * any of these options should simply ignore them.
188  *
189  * tftp_open() will not automatically join or leave multicast groups;
190  * the caller is responsible for calling join_group() and
191  * leave_group() at appropriate times.
192  *
193  * If the response from the server is a TFTP ERROR packet, tftp_open()
194  * will return False and #errno will be set accordingly.
195  */
196 int tftp_open ( struct tftp_state *state, const char *filename,
197                 union tftp_any **reply ) {
198         static unsigned short lport = 2000; /* local port */
199         int fixed_lport;
200         struct tftp_rrq rrq;
201         unsigned int rrqlen;
202         int retry;
203
204         /* Flush receive queue */
205         rx_qdrain();
206
207         /* Default to blksize of TFTP_MAX_BLKSIZE if none specified */
208         if ( ! state->blksize )
209                 state->blksize = TFTP_MAX_BLKSIZE;
210
211         /* Use default TFTP server port if none specified */
212         if ( ! state->server.sin_port )
213                 state->server.sin_port = TFTP_PORT;
214
215         /* Determine whether or not to use lport */
216         fixed_lport = state->client.sin_port;
217
218         /* Set up RRQ */
219         rrq.opcode = htons ( TFTP_RRQ );
220         rrqlen = ( offsetof ( typeof ( rrq ), data ) +
221                     sprintf ( rrq.data,
222                               "%s%coctet%cblksize%c%d%ctsize%c0%cmulticast%c",
223                               filename, 0, 0, 0, state->blksize, 0, 0, 0, 0 )
224                     + 1 );
225
226         /* Set negotiated blksize to default value */
227         state->blksize = TFTP_DEFAULT_BLKSIZE;
228         
229         /* Nullify received packet pointer */
230         *reply = NULL;
231
232         /* Transmit RRQ until we get a response */
233         for ( retry = 0 ; retry < MAX_TFTP_RETRIES ; retry++ ) {
234                 long timeout = rfc2131_sleep_interval ( TIMEOUT, retry );
235
236                 /* Set client UDP port, if not already fixed */
237                 if ( ! fixed_lport )
238                         state->client.sin_port = ++lport;
239                 
240                 /* Send the RRQ */
241                 DBG ( "TFTPCORE: requesting %@:%d/%s from port %d\n",
242                       state->server.sin_addr.s_addr, state->server.sin_port,
243                       rrq.data, state->client.sin_port );
244                 if ( ! udp_transmit ( state->server.sin_addr.s_addr,
245                                       state->client.sin_port,
246                                       state->server.sin_port,
247                                       rrqlen, &rrq ) )
248                         return 0;
249                 
250                 /* Wait for response */
251                 if ( tftp_get ( state, timeout, reply ) ) {
252                         /* We got a non-error response */
253                         state->server.sin_port
254                                 = ntohs ( (*reply)->common.udp.src );
255                         DBG ( "TFTP server is at %@:%d\n",
256                               state->server.sin_addr.s_addr,
257                               state->server.sin_port );
258                         return 1;
259                 }
260                 if ( reply ) {
261                         /* We got an error response; abort */
262                         return 0;
263                 }
264         }
265
266         DBG ( "TFTPCORE: open request timed out\n" );
267         errno = PXENV_STATUS_TFTP_OPEN_TIMEOUT;
268         return 0;
269 }
270
271 /**
272  * Process a TFTP OACK packet
273  *
274  * @v state                             TFTP transfer state
275  * @v oack                              The TFTP OACK packet
276  * @ret True                            Options were processed successfully
277  * @ret False                           Options were not processed successfully
278  * @ret tftp_state::blksize             Negotiated blksize
279  * @ret tftp_state::tsize               File size (if known), or 0
280  * @ret tftp_state::client::sin_addr    Client multicast IP address, or 0.0.0.0
281  * @ret tftp_state::client::sin_port    Client UDP port
282  * @ret tftp_state::master              Client is master
283  * @err EINVAL                          An invalid option value was encountered
284  *
285  * Process the options returned by the TFTP server in an rfc2347 OACK
286  * packet.  The options "blksize" (rfc2348), "tsize" (rfc2349) and
287  * "multicast" (rfc2090) are recognised and processed; any other
288  * options are silently ignored.
289  *
290  * Where an option is not present in the OACK packet, the
291  * corresponding field(s) in #state will be left unaltered.
292  *
293  * Calling tftp_process_opts() does not send an acknowledgement for
294  * the OACK packet; this is the responsibility of the caller.
295  *
296  * @note If the "blksize" option is not present, tftp_state::blksize
297  * will @b not be implicitly set to #TFTP_DEFAULT_BLKSIZE.  However,
298  * since tftp_open() always sets tftp_state::blksize to
299  * #TFTP_DEFAULT_BLKSIZE before returning, you probably don't need to
300  * worry about this.
301  */
302 int tftp_process_opts ( struct tftp_state *state, struct tftp_oack *oack ) {
303         const char *p;
304         const char *end;
305
306         DBG ( "TFTPCORE: processing OACK\n" );
307
308         /* End of options */
309         end = ( ( char * ) &oack->udp ) + ntohs ( oack->udp.len );
310
311         /* Only possible error */
312         errno = EINVAL;
313
314         for ( p = oack->data ; p < end ; ) {
315                 if ( strcasecmp ( "blksize", p ) == 0 ) {
316                         p += 8;
317                         state->blksize = strtoul ( p, &p, 10 );
318                         if ( *p ) {
319                                 DBG ( "TFTPCORE: garbage \"%s\" "
320                                       "after blksize\n", p );
321                                 return 0;
322                         }
323                         p++;
324                         DBG ( "TFTPCORE: got blksize %d\n", state->blksize );
325                 } else if ( strcasecmp ( "tsize", p ) == 0 ) {
326                         p += 6;
327                         state->tsize = strtoul ( p, &p, 10 );
328                         if ( *p ) {
329                                 DBG ( "TFTPCORE: garbage \"%s\" "
330                                       "after tsize\n", p );
331                                 return 0;
332                         }
333                         p++;
334                         DBG ( "TFTPCORE: got tsize %d\n", state->tsize );
335                 } else if ( strcasecmp ( "multicast", p ) == 0 ) {
336                         char *e = strchr ( p, ',' );
337                         if ( ( ! e ) || ( e >= end ) ) {
338                                 DBG ( "TFTPCORE: malformed multicast field "
339                                       "\"%s\"\n", p );
340                                 return 0;
341                         }
342                         /* IP address may be missing, in which case we
343                          * should leave state->client.sin_addr
344                          * unaltered.
345                          */
346                         if ( e != p ) {
347                                 int rc;
348                                 *e = '\0';
349                                 rc = inet_aton ( p, &state->client.sin_addr );
350                                 *e = ',';
351                                 if ( ! rc ) {
352                                         DBG ( "TFTPCORE: malformed multicast "
353                                               "IP address \"%s\"\n", p );
354                                         return 0;
355                                 }
356                         }
357                         p = e + 1;
358                         /* UDP port may also be missing */
359                         if ( *p != ',' ) {
360                                 state->client.sin_port = strtoul ( p, &p, 10 );
361                                 if ( *p != ',' ) {
362                                         DBG ( "TFTPCORE: garbage \"%s\" "
363                                               "after multicast port\n", p );
364                                         return 0;
365                                 }
366                         } else {
367                                 p++;
368                         }
369                         /* "Master Client" must always be present */
370                         state->master = strtoul ( p, &p, 10 );
371                         if ( *p ) {
372                                 DBG ( "TFTPCORE: garbage \"%s\" "
373                                       "after multicast mc\n", p );
374                                 return 0;
375                         }
376                         p++;
377                         DBG ( "TFTPCORE: got multicast %@:%d (%s)\n",
378                               state->client.sin_addr.s_addr,
379                               state->client.sin_port,
380                               ( state->master ? "master" : "not master" ) );
381                 } else {
382                         DBG ( "TFTPCORE: unknown option \"%s\"\n", p );
383                         p += strlen ( p ) + 1; /* skip option name */
384                         p += strlen ( p ) + 1; /* skip option value */
385                 }
386         }
387
388         if ( p > end ) {
389                 DBG ( "TFTPCORE: overran options in OACK\n" );
390                 return 0;
391         }
392
393         return 1;
394 }
395
396 /**
397  * Acknowledge a TFTP packet
398  *
399  * @v state                             TFTP transfer state
400  * @v tftp_state::server::sin_addr      TFTP server IP address
401  * @v tftp_state::server::sin_port      TFTP server UDP port
402  * @v tftp_state::client::sin_port      Client UDP port
403  * @v tftp_state::block                 Most recently received block number
404  * @ret True                            Acknowledgement packet was sent
405  * @ret False                           Acknowledgement packet was not sent
406  * @err other                           As returned by udp_transmit()
407  * 
408  * Send a TFTP ACK packet for the most recently received block.
409  *
410  * This sends only a single ACK packet; it does not wait for the
411  * server's response.
412  */
413 int tftp_ack_nowait ( struct tftp_state *state ) {
414         struct tftp_ack ack;
415
416         DBG ( "TFTPCORE: acknowledging data block %d\n", state->block );
417         ack.opcode = htons ( TFTP_ACK );
418         ack.block = htons ( state->block );
419         return udp_transmit ( state->server.sin_addr.s_addr,
420                               state->client.sin_port, state->server.sin_port,
421                               sizeof ( ack ), &ack );
422 }
423
424 /**
425  * Acknowledge a TFTP packet and wait for a response
426  *
427  * @v state                             TFTP transfer state
428  * @v tftp_state::server::sin_addr      TFTP server IP address
429  * @v tftp_state::server::sin_port      TFTP server UDP port
430  * @v tftp_state::client::sin_port      Client UDP port
431  * @v tftp_state::block                 Most recently received block number
432  * @ret True                            Received a non-error response
433  * @ret False                           Received error response / no response
434  * @ret *reply                          The server's response, if any
435  * @err #PXENV_STATUS_TFTP_READ_TIMEOUT Timed out waiting for a response
436  * @err other                           As returned by tftp_ack_nowait()
437  * @err other                           As set by tftp_set_errno()
438  *
439  * Send a TFTP ACK packet for the most recently received data block,
440  * and keep transmitting this ACK until we get a response from the
441  * server (e.g. a new data block).
442  *
443  * If the response is a TFTP DATA packet, no processing is done.
444  * Specifically, the block number is not checked to ensure that this
445  * is indeed the next data block in the sequence, nor is
446  * tftp_state::block updated with the new block number.
447  *
448  * If the response from the server is a TFTP ERROR packet, tftp_open()
449  * will return False and #errno will be set accordingly.
450  */
451 int tftp_ack ( struct tftp_state *state, union tftp_any **reply ) {
452         int retry;
453
454         *reply = NULL;
455         for ( retry = 0 ; retry < MAX_TFTP_RETRIES ; retry++ ) {
456                 long timeout = rfc2131_sleep_interval ( TFTP_REXMT, retry );
457                 /* ACK the last data block */
458                 if ( ! tftp_ack_nowait ( state ) ) {
459                         DBG ( "TFTP: could not send ACK: %m\n" );
460                         return 0;
461                 }
462                 if ( tftp_get ( state, timeout, reply ) ) {
463                         /* We got a non-error response */
464                         return 1;
465                 }
466                 if ( reply ) {
467                         /* We got an error response */
468                         return 0;
469                 }
470         }
471         DBG ( "TFTP: timed out during read\n" );
472         errno = PXENV_STATUS_TFTP_READ_TIMEOUT;
473         return 0;
474 }
475
476 /**
477  * Send a TFTP error
478  *
479  * @v state                             TFTP transfer state
480  * @v tftp_state::server::sin_addr      TFTP server IP address
481  * @v tftp_state::server::sin_port      TFTP server UDP port
482  * @v tftp_state::client::sin_port      Client UDP port
483  * @v errcode                           TFTP error code
484  * @v errmsg                            Descriptive error string, or NULL
485  * @ret True                            Error packet was sent
486  * @ret False                           Error packet was not sent
487  *
488  * Send a TFTP ERROR packet back to the server to terminate the
489  * transfer.
490  *
491  * If #errmsg is NULL, the current error message string as returned by
492  * strerror(errno) will be used as the error text.
493  */
494 int tftp_error ( struct tftp_state *state, int errcode, const char *errmsg ) {
495         struct tftp_error error;
496
497         DBG ( "TFTPCORE: aborting with error %d (%s)\n", errcode, errmsg );
498         error.opcode = htons ( TFTP_ERROR );
499         error.errcode = htons ( errcode );
500         strncpy ( error.errmsg, errmsg ? errmsg : strerror ( errno ),
501                   sizeof ( error.errmsg ) );
502         return udp_transmit ( state->server.sin_addr.s_addr,
503                               state->client.sin_port, state->server.sin_port,
504                               sizeof ( error ), &error );
505 }
506
507 /**
508  * Interpret a TFTP error
509  *
510  * @v error                             Pointer to a struct tftp_error
511  *
512  * Sets #errno based on the error code in a TFTP ERROR packet.
513  */
514 void tftp_set_errno ( struct tftp_error *error ) {
515         static int errmap[] = {
516                 [TFTP_ERR_FILE_NOT_FOUND] = PXENV_STATUS_TFTP_FILE_NOT_FOUND,
517                 [TFTP_ERR_ACCESS_DENIED] = PXENV_STATUS_TFTP_ACCESS_VIOLATION,
518                 [TFTP_ERR_ILLEGAL_OP] = PXENV_STATUS_TFTP_UNKNOWN_OPCODE,
519         };
520         unsigned int errcode = ntohs ( error->errcode );
521         
522         errno = 0;
523         if ( errcode < ( sizeof(errmap) / sizeof(errmap[0]) ) )
524                 errno = errmap[errcode];
525         if ( ! errno )
526                 errno = PXENV_STATUS_TFTP_ERROR_OPCODE;
527 }