74c8c0a5faf18bf88b5543813349d88a107256bd
[people/xl0/gpxe.git] / src / net / udp / tftp.c
1 /*
2  * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18
19 #include <stdint.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <strings.h>
24 #include <byteswap.h>
25 #include <errno.h>
26 #include <assert.h>
27 #include <gpxe/refcnt.h>
28 #include <gpxe/xfer.h>
29 #include <gpxe/open.h>
30 #include <gpxe/uri.h>
31 #include <gpxe/tcpip.h>
32 #include <gpxe/retry.h>
33 #include <gpxe/features.h>
34 #include <gpxe/tftp.h>
35
36 /** @file
37  *
38  * TFTP protocol
39  *
40  */
41
42 FEATURE ( FEATURE_PROTOCOL, "TFTP", DHCP_EB_FEATURE_TFTP, 1 );
43
44 /**
45  * A TFTP request
46  *
47  * This data structure holds the state for an ongoing TFTP transfer.
48  */
49 struct tftp_request {
50         /** Reference count */
51         struct refcnt refcnt;
52         /** Data transfer interface */
53         struct xfer_interface xfer;
54
55         /** URI being fetched */
56         struct uri *uri;
57         /** Transport layer interface */
58         struct xfer_interface socket;
59
60         /** Data block size
61          *
62          * This is the "blksize" option negotiated with the TFTP
63          * server.  (If the TFTP server does not support TFTP options,
64          * this will default to 512).
65          */
66         unsigned int blksize;
67         /** File size
68          *
69          * This is the value returned in the "tsize" option from the
70          * TFTP server.  If the TFTP server does not support the
71          * "tsize" option, this value will be zero.
72          */
73         unsigned long tsize;
74
75         /** Request state
76          *
77          * This is the block number to be used in the next ACK sent
78          * back to the server, i.e. the number of the last received
79          * data block.  The value zero indicates that the last
80          * received block was an OACK (i.e. that the next ACK will
81          * contain a block number of zero), and any value less than
82          * zero indicates that the connection has not yet been opened
83          * (i.e. that no blocks have yet been received).
84          */
85         int state;
86         /** Peer address
87          *
88          * The peer address is determined by the first response
89          * received to the TFTP RRQ.
90          */
91         struct sockaddr_tcpip peer;
92         /** Retransmission timer */
93         struct retry_timer timer;
94 };
95
96 /**
97  * Free TFTP request
98  *
99  * @v refcnt            Reference counter
100  */
101 static void tftp_free ( struct refcnt *refcnt ) {
102         struct tftp_request *tftp =
103                 container_of ( refcnt, struct tftp_request, refcnt );
104
105         uri_put ( tftp->uri );
106         free ( tftp );
107 }
108
109 /**
110  * Mark TFTP request as complete
111  *
112  * @v tftp              TFTP connection
113  * @v rc                Return status code
114  */
115 static void tftp_done ( struct tftp_request *tftp, int rc ) {
116
117         DBGC ( tftp, "TFTP %p finished with status %d (%s)\n",
118                tftp, rc, strerror ( rc ) );
119
120         /* Stop the retry timer */
121         stop_timer ( &tftp->timer );
122
123         /* Close all data transfer interfaces */
124         xfer_nullify ( &tftp->socket );
125         xfer_close ( &tftp->socket, rc );
126         xfer_nullify ( &tftp->xfer );
127         xfer_close ( &tftp->xfer, rc );
128 }
129
130 /**
131  * TFTP requested blocksize
132  *
133  * This is treated as a global configuration parameter.
134  */
135 static unsigned int tftp_request_blksize = TFTP_MAX_BLKSIZE;
136
137 /**
138  * Set TFTP request blocksize
139  *
140  * @v blksize           Requested block size
141  */
142 void tftp_set_request_blksize ( unsigned int blksize ) {
143         if ( blksize < TFTP_DEFAULT_BLKSIZE )
144                 blksize = TFTP_DEFAULT_BLKSIZE;
145         tftp_request_blksize = blksize;
146 }
147
148 /**
149  * Transmit RRQ
150  *
151  * @v tftp              TFTP connection
152  * @ret rc              Return status code
153  */
154 static int tftp_send_rrq ( struct tftp_request *tftp ) {
155         struct tftp_rrq *rrq;
156         const char *path = tftp->uri->path;
157         size_t len = ( sizeof ( *rrq ) + strlen ( path ) + 1 /* NUL */
158                        + 5 + 1 /* "octet" + NUL */
159                        + 7 + 1 + 5 + 1 /* "blksize" + NUL + ddddd + NUL */
160                        + 5 + 1 + 1 + 1 /* "tsize" + NUL + "0" + NUL */ );
161         struct io_buffer *iobuf;
162
163         DBGC ( tftp, "TFTP %p requesting \"%s\"\n", tftp, path );
164
165         /* Allocate buffer */
166         iobuf = xfer_alloc_iob ( &tftp->socket, len );
167         if ( ! iobuf )
168                 return -ENOMEM;
169
170         /* Build request */
171         rrq = iob_put ( iobuf, sizeof ( *rrq ) );
172         rrq->opcode = htons ( TFTP_RRQ );
173         iob_put ( iobuf,
174                   snprintf ( rrq->data, iob_tailroom ( iobuf ),
175                              "%s%coctet%cblksize%c%d%ctsize%c0", path, 0,
176                              0, 0, tftp_request_blksize, 0, 0 ) + 1 );
177
178         /* RRQ always goes to the address specified in the initial
179          * xfer_open() call
180          */
181         return xfer_deliver_iob ( &tftp->socket, iobuf );
182 }
183
184 /**
185  * Transmit ACK
186  *
187  * @v tftp              TFTP connection
188  * @ret rc              Return status code
189  */
190 static int tftp_send_ack ( struct tftp_request *tftp ) {
191         struct tftp_ack *ack;
192         struct io_buffer *iobuf;
193         struct xfer_metadata meta = {
194                 .dest = ( struct sockaddr * ) &tftp->peer,
195         };
196
197         DBGC2 ( tftp, "TFTP %p sending ACK for block %d\n",
198                 tftp, tftp->state );
199
200         /* Allocate buffer */
201         iobuf = xfer_alloc_iob ( &tftp->socket, sizeof ( *ack ) );
202         if ( ! iobuf )
203                 return -ENOMEM;
204
205         /* Build ACK */
206         ack = iob_put ( iobuf, sizeof ( *ack ) );
207         ack->opcode = htons ( TFTP_ACK );
208         ack->block = htons ( tftp->state );
209
210         /* ACK always goes to the peer recorded from the RRQ response */
211         return xfer_deliver_iob_meta ( &tftp->socket, iobuf, &meta );
212 }
213
214 /**
215  * Transmit data
216  *
217  * @v tftp              TFTP connection
218  * @ret rc              Return status code
219  */
220 static int tftp_send_packet ( struct tftp_request *tftp ) {
221
222         /* Start retransmission timer */
223         start_timer ( &tftp->timer );
224
225         /* Send RRQ or ACK as appropriate */
226         if ( tftp->state < 0 ) {
227                 return tftp_send_rrq ( tftp );
228         } else {
229                 return tftp_send_ack ( tftp );
230         }
231 }
232
233 /**
234  * Handle TFTP retransmission timer expiry
235  *
236  * @v timer             Retry timer
237  * @v fail              Failure indicator
238  */
239 static void tftp_timer_expired ( struct retry_timer *timer, int fail ) {
240         struct tftp_request *tftp =
241                 container_of ( timer, struct tftp_request, timer );
242
243         if ( fail ) {
244                 tftp_done ( tftp, -ETIMEDOUT );
245         } else {
246                 tftp_send_packet ( tftp );
247         }
248 }
249
250 /**
251  * Mark TFTP block as received
252  *
253  * @v tftp              TFTP connection
254  * @v block             Block number
255  */
256 static void tftp_received ( struct tftp_request *tftp, unsigned int block ) {
257
258         /* Stop the retry timer */
259         stop_timer ( &tftp->timer );
260
261         /* Update state to indicate which block we're now waiting for */
262         tftp->state = block;
263
264         /* Send next packet */
265         tftp_send_packet ( tftp );
266 }
267
268 /**
269  * Process TFTP "blksize" option
270  *
271  * @v tftp              TFTP connection
272  * @v value             Option value
273  * @ret rc              Return status code
274  */
275 static int tftp_process_blksize ( struct tftp_request *tftp,
276                                   const char *value ) {
277         char *end;
278
279         tftp->blksize = strtoul ( value, &end, 10 );
280         if ( *end ) {
281                 DBGC ( tftp, "TFTP %p got invalid blksize \"%s\"\n",
282                        tftp, value );
283                 return -EINVAL;
284         }
285         DBGC ( tftp, "TFTP %p blksize=%d\n", tftp, tftp->blksize );
286
287         return 0;
288 }
289
290 /**
291  * Process TFTP "tsize" option
292  *
293  * @v tftp              TFTP connection
294  * @v value             Option value
295  * @ret rc              Return status code
296  */
297 static int tftp_process_tsize ( struct tftp_request *tftp,
298                                 const char *value ) {
299         char *end;
300
301         tftp->tsize = strtoul ( value, &end, 10 );
302         if ( *end ) {
303                 DBGC ( tftp, "TFTP %p got invalid tsize \"%s\"\n",
304                        tftp, value );
305                 return -EINVAL;
306         }
307         DBGC ( tftp, "TFTP %p tsize=%ld\n", tftp, tftp->tsize );
308
309         /* Notify recipient of file size */
310         xfer_seek ( &tftp->xfer, tftp->tsize, SEEK_SET );
311         xfer_seek ( &tftp->xfer, 0, SEEK_SET );
312
313         return 0;
314 }
315
316 /** A TFTP option */
317 struct tftp_option {
318         /** Option name */
319         const char *name;
320         /** Option processor
321          *
322          * @v tftp      TFTP connection
323          * @v value     Option value
324          * @ret rc      Return status code
325          */
326         int ( * process ) ( struct tftp_request *tftp, const char *value );
327 };
328
329 /** Recognised TFTP options */
330 static struct tftp_option tftp_options[] = {
331         { "blksize", tftp_process_blksize },
332         { "tsize", tftp_process_tsize },
333         { NULL, NULL }
334 };
335
336 /**
337  * Process TFTP option
338  *
339  * @v tftp              TFTP connection
340  * @v name              Option name
341  * @v value             Option value
342  * @ret rc              Return status code
343  */
344 static int tftp_process_option ( struct tftp_request *tftp,
345                                  const char *name, const char *value ) {
346         struct tftp_option *option;
347
348         for ( option = tftp_options ; option->name ; option++ ) {
349                 if ( strcasecmp ( name, option->name ) == 0 )
350                         return option->process ( tftp, value );
351         }
352
353         DBGC ( tftp, "TFTP %p received unknown option \"%s\" = \"%s\"\n",
354                tftp, name, value );
355
356         return -EINVAL;
357 }
358
359 /**
360  * Receive OACK
361  *
362  * @v tftp              TFTP connection
363  * @v buf               Temporary data buffer
364  * @v len               Length of temporary data buffer
365  * @ret rc              Return status code
366  */
367 static int tftp_rx_oack ( struct tftp_request *tftp, void *buf, size_t len ) {
368         struct tftp_oack *oack = buf;
369         char *end = buf + len;
370         char *name;
371         char *value;
372         int rc;
373
374         /* Sanity check */
375         if ( len < sizeof ( *oack ) ) {
376                 DBGC ( tftp, "TFTP %p received underlength OACK packet "
377                        "length %d\n", tftp, len );
378                 return -EINVAL;
379         }
380         if ( end[-1] != '\0' ) {
381                 DBGC ( tftp, "TFTP %p received OACK missing final NUL\n",
382                        tftp );
383                 return -EINVAL;
384         }
385
386         /* Process each option in turn */
387         name = oack->data;
388         while ( name < end ) {
389                 value = ( name + strlen ( name ) + 1 );
390                 if ( value == end ) {
391                         DBGC ( tftp, "TFTP %p received OACK missing value "
392                                "for option \"%s\"\n", tftp, name );
393                         return -EINVAL;
394                 }
395                 if ( ( rc = tftp_process_option ( tftp, name, value ) ) != 0 )
396                         return rc;
397                 name = ( value + strlen ( value ) + 1 );
398         }
399
400         /* Mark as received block 0 (the OACK) */
401         tftp_received ( tftp, 0 );
402
403         return 0;
404 }
405
406 /**
407  * Receive DATA
408  *
409  * @v tftp              TFTP connection
410  * @v iobuf             I/O buffer
411  * @ret rc              Return status code
412  *
413  * Takes ownership of I/O buffer.
414  */
415 static int tftp_rx_data ( struct tftp_request *tftp,
416                           struct io_buffer *iobuf ) {
417         struct tftp_data *data = iobuf->data;
418         unsigned int block;
419         size_t data_len;
420         int rc;
421
422         /* Sanity check */
423         if ( iob_len ( iobuf ) < sizeof ( *data ) ) {
424                 DBGC ( tftp, "TFTP %p received underlength DATA packet "
425                        "length %d\n", tftp, iob_len ( iobuf ) );
426                 free_iob ( iobuf );
427                 return -EINVAL;
428         }
429
430         /* Extract data */
431         block = ntohs ( data->block );
432         iob_pull ( iobuf, sizeof ( *data ) );
433         data_len = iob_len ( iobuf );
434
435         /* Deliver data */
436         if ( ( rc = xfer_deliver_iob ( &tftp->xfer, iobuf ) ) != 0 ) {
437                 DBGC ( tftp, "TFTP %p could not deliver data: %s\n",
438                        tftp, strerror ( rc ) );
439                 tftp_done ( tftp, rc );
440                 return rc;
441         }
442
443         /* Mark block as received */
444         tftp_received ( tftp, block );
445
446         /* Finish when final block received */
447         if ( data_len < tftp->blksize )
448                 tftp_done ( tftp, 0 );
449
450         return 0;
451 }
452
453 /** Translation between TFTP errors and internal error numbers */
454 static const uint8_t tftp_errors[] = {
455         [TFTP_ERR_FILE_NOT_FOUND]       = PXENV_STATUS_TFTP_FILE_NOT_FOUND,
456         [TFTP_ERR_ACCESS_DENIED]        = PXENV_STATUS_TFTP_ACCESS_VIOLATION,
457         [TFTP_ERR_ILLEGAL_OP]           = PXENV_STATUS_TFTP_UNKNOWN_OPCODE,
458 };
459
460 /**
461  * Receive ERROR
462  *
463  * @v tftp              TFTP connection
464  * @v buf               Temporary data buffer
465  * @v len               Length of temporary data buffer
466  * @ret rc              Return status code
467  */
468 static int tftp_rx_error ( struct tftp_request *tftp, void *buf, size_t len ) {
469         struct tftp_error *error = buf;
470         unsigned int err;
471         int rc = 0;
472
473         /* Sanity check */
474         if ( len < sizeof ( *error ) ) {
475                 DBGC ( tftp, "TFTP %p received underlength ERROR packet "
476                        "length %d\n", tftp, len );
477                 return -EINVAL;
478         }
479
480         DBGC ( tftp, "TFTP %p received ERROR packet with code %d, message "
481                "\"%s\"\n", tftp, ntohs ( error->errcode ), error->errmsg );
482         
483         /* Determine final operation result */
484         err = ntohs ( error->errcode );
485         if ( err < ( sizeof ( tftp_errors ) / sizeof ( tftp_errors[0] ) ) )
486                 rc = -tftp_errors[err];
487         if ( ! rc )
488                 rc = -PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION;
489
490         /* Close TFTP request */
491         tftp_done ( tftp, rc );
492
493         return 0;
494 }
495
496 /**
497  * Receive new data
498  *
499  * @v udp               UDP connection
500  * @v data              Received data
501  * @v len               Length of received data
502  * @v st_src            Partially-filled source address
503  * @v st_dest           Partially-filled destination address
504  */
505 static int tftp_socket_deliver_iob ( struct xfer_interface *socket,
506                                      struct io_buffer *iobuf,
507                                      struct xfer_metadata *meta ) {
508         struct tftp_request *tftp =
509                 container_of ( socket, struct tftp_request, socket );
510         struct sockaddr_tcpip *st_src;
511         struct tftp_common *common = iobuf->data;
512         size_t len = iob_len ( iobuf );
513         int rc = -EINVAL;
514         
515         /* Sanity checks */
516         if ( len < sizeof ( *common ) ) {
517                 DBGC ( tftp, "TFTP %p received underlength packet length %d\n",
518                        tftp, len );
519                 goto done;
520         }
521         if ( ! meta ) {
522                 DBGC ( tftp, "TFTP %p received packet without metadata\n",
523                        tftp );
524                 goto done;
525         }
526         if ( ! meta->src ) {
527                 DBGC ( tftp, "TFTP %p received packet without source port\n",
528                        tftp );
529                 goto done;
530         }
531
532         /* Filter by TID.  Set TID on first response received */
533         st_src = ( struct sockaddr_tcpip * ) meta->src;
534         if ( tftp->state < 0 ) {
535                 memcpy ( &tftp->peer, st_src, sizeof ( tftp->peer ) );
536                 DBGC ( tftp, "TFTP %p using remote port %d\n", tftp,
537                        ntohs ( tftp->peer.st_port ) );
538         } else if ( memcmp ( &tftp->peer, st_src,
539                              sizeof ( tftp->peer ) ) != 0 ) {
540                 DBGC ( tftp, "TFTP %p received packet from wrong source (got "
541                        "%d, wanted %d)\n", tftp, ntohs ( st_src->st_port ),
542                        ntohs ( tftp->peer.st_port ) );
543                 goto done;
544         }
545
546         switch ( common->opcode ) {
547         case htons ( TFTP_OACK ):
548                 rc = tftp_rx_oack ( tftp, iobuf->data, len );
549                 break;
550         case htons ( TFTP_DATA ):
551                 rc = tftp_rx_data ( tftp, iobuf );
552                 iobuf = NULL;
553                 break;
554         case htons ( TFTP_ERROR ):
555                 rc = tftp_rx_error ( tftp, iobuf->data, len );
556                 break;
557         default:
558                 DBGC ( tftp, "TFTP %p received strange packet type %d\n",
559                        tftp, ntohs ( common->opcode ) );
560                 break;
561         };
562
563  done:
564         free_iob ( iobuf );
565         return rc;
566 }
567
568 /**
569  * TFTP connection closed by network stack
570  *
571  * @v socket            Transport layer interface
572  * @v rc                Reason for close
573  */
574 static void tftp_socket_close ( struct xfer_interface *socket, int rc ) {
575         struct tftp_request *tftp =
576                 container_of ( socket, struct tftp_request, socket );
577
578         DBGC ( tftp, "TFTP %p socket closed: %s\n",
579                tftp, strerror ( rc ) );
580
581         tftp_done ( tftp, rc );
582 }
583
584 /** TFTP socket operations */
585 static struct xfer_interface_operations tftp_socket_operations = {
586         .close          = tftp_socket_close,
587         .vredirect      = xfer_vopen,
588         .seek           = ignore_xfer_seek,
589         .window         = unlimited_xfer_window,
590         .alloc_iob      = default_xfer_alloc_iob,
591         .deliver_iob    = tftp_socket_deliver_iob,
592         .deliver_raw    = xfer_deliver_as_iob,
593 };
594  
595 /**
596  * Close TFTP data transfer interface
597  *
598  * @v xfer              Data transfer interface
599  * @v rc                Reason for close
600  */
601 static void tftp_xfer_close ( struct xfer_interface *xfer, int rc ) {
602         struct tftp_request *tftp =
603                 container_of ( xfer, struct tftp_request, xfer );
604
605         DBGC ( tftp, "TFTP %p interface closed: %s\n",
606                tftp, strerror ( rc ) );
607
608         tftp_done ( tftp, rc );
609 }
610
611 /** TFTP data transfer interface operations */
612 static struct xfer_interface_operations tftp_xfer_operations = {
613         .close          = tftp_xfer_close,
614         .vredirect      = ignore_xfer_vredirect,
615         .seek           = ignore_xfer_seek,
616         .window         = unlimited_xfer_window,
617         .alloc_iob      = default_xfer_alloc_iob,
618         .deliver_iob    = xfer_deliver_as_raw,
619         .deliver_raw    = ignore_xfer_deliver_raw,
620 };
621
622 /**
623  * Initiate TFTP download
624  *
625  * @v xfer              Data transfer interface
626  * @v uri               Uniform Resource Identifier
627  * @ret rc              Return status code
628  */
629 int tftp_open ( struct xfer_interface *xfer, struct uri *uri ) {
630         struct tftp_request *tftp;
631         struct sockaddr_tcpip server;
632         int rc;
633
634         /* Sanity checks */
635         if ( ! uri->host )
636                 return -EINVAL;
637         if ( ! uri->path )
638                 return -EINVAL;
639
640         /* Allocate and populate TFTP structure */
641         tftp = zalloc ( sizeof ( *tftp ) );
642         if ( ! tftp )
643                 return -ENOMEM;
644         tftp->refcnt.free = tftp_free;
645         xfer_init ( &tftp->xfer, &tftp_xfer_operations, &tftp->refcnt );
646         tftp->uri = uri_get ( uri );
647         xfer_init ( &tftp->socket, &tftp_socket_operations, &tftp->refcnt );
648         tftp->blksize = TFTP_DEFAULT_BLKSIZE;
649         tftp->state = -1;
650         tftp->timer.expired = tftp_timer_expired;
651
652         /* Open socket */
653         memset ( &server, 0, sizeof ( server ) );
654         server.st_port = htons ( uri_port ( tftp->uri, TFTP_PORT ) );
655         if ( ( rc = xfer_open_named_socket ( &tftp->socket, SOCK_DGRAM,
656                                              ( struct sockaddr * ) &server,
657                                              uri->host, NULL ) ) != 0 )
658                 goto err;
659
660         /* Start timer to initiate RRQ */
661         start_timer_nodelay ( &tftp->timer );
662
663         /* Attach to parent interface, mortalise self, and return */
664         xfer_plug_plug ( &tftp->xfer, xfer );
665         ref_put ( &tftp->refcnt );
666         return 0;
667
668  err:
669         DBGC ( tftp, "TFTP %p could not create request: %s\n",
670                tftp, strerror ( rc ) );
671         tftp_done ( tftp, rc );
672         ref_put ( &tftp->refcnt );
673         return rc;
674 }
675
676 /** TFTP URI opener */
677 struct uri_opener tftp_uri_opener __uri_opener = {
678         .scheme = "tftp",
679         .open   = tftp_open,
680 };