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