Check for correct block number in tftp_rx_data().
[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         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         /* Check for correct block */
436         if ( block != ( tftp->state + 1 ) ) {
437                 DBGC ( tftp, "TFTP %p received out-of-order block %d "
438                        "(expecting %d)\n", tftp, block, ( tftp->state + 1 ) );
439                 free_iob ( iobuf );
440                 return 0;
441         }
442
443         /* Deliver data */
444         if ( ( rc = xfer_deliver_iob ( &tftp->xfer, iobuf ) ) != 0 ) {
445                 DBGC ( tftp, "TFTP %p could not deliver data: %s\n",
446                        tftp, strerror ( rc ) );
447                 tftp_done ( tftp, rc );
448                 return rc;
449         }
450
451         /* Mark block as received */
452         tftp_received ( tftp, block );
453
454         /* Finish when final block received */
455         if ( data_len < tftp->blksize )
456                 tftp_done ( tftp, 0 );
457
458         return 0;
459 }
460
461 /** Translation between TFTP errors and internal error numbers */
462 static const uint8_t tftp_errors[] = {
463         [TFTP_ERR_FILE_NOT_FOUND]       = PXENV_STATUS_TFTP_FILE_NOT_FOUND,
464         [TFTP_ERR_ACCESS_DENIED]        = PXENV_STATUS_TFTP_ACCESS_VIOLATION,
465         [TFTP_ERR_ILLEGAL_OP]           = PXENV_STATUS_TFTP_UNKNOWN_OPCODE,
466 };
467
468 /**
469  * Receive ERROR
470  *
471  * @v tftp              TFTP connection
472  * @v buf               Temporary data buffer
473  * @v len               Length of temporary data buffer
474  * @ret rc              Return status code
475  */
476 static int tftp_rx_error ( struct tftp_request *tftp, void *buf, size_t len ) {
477         struct tftp_error *error = buf;
478         unsigned int err;
479         int rc = 0;
480
481         /* Sanity check */
482         if ( len < sizeof ( *error ) ) {
483                 DBGC ( tftp, "TFTP %p received underlength ERROR packet "
484                        "length %d\n", tftp, len );
485                 return -EINVAL;
486         }
487
488         DBGC ( tftp, "TFTP %p received ERROR packet with code %d, message "
489                "\"%s\"\n", tftp, ntohs ( error->errcode ), error->errmsg );
490         
491         /* Determine final operation result */
492         err = ntohs ( error->errcode );
493         if ( err < ( sizeof ( tftp_errors ) / sizeof ( tftp_errors[0] ) ) )
494                 rc = -tftp_errors[err];
495         if ( ! rc )
496                 rc = -PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION;
497
498         /* Close TFTP request */
499         tftp_done ( tftp, rc );
500
501         return 0;
502 }
503
504 /**
505  * Receive new data
506  *
507  * @v udp               UDP connection
508  * @v data              Received data
509  * @v len               Length of received data
510  * @v st_src            Partially-filled source address
511  * @v st_dest           Partially-filled destination address
512  */
513 static int tftp_socket_deliver_iob ( struct xfer_interface *socket,
514                                      struct io_buffer *iobuf,
515                                      struct xfer_metadata *meta ) {
516         struct tftp_request *tftp =
517                 container_of ( socket, struct tftp_request, socket );
518         struct sockaddr_tcpip *st_src;
519         struct tftp_common *common = iobuf->data;
520         size_t len = iob_len ( iobuf );
521         int rc = -EINVAL;
522         
523         /* Sanity checks */
524         if ( len < sizeof ( *common ) ) {
525                 DBGC ( tftp, "TFTP %p received underlength packet length %d\n",
526                        tftp, len );
527                 goto done;
528         }
529         if ( ! meta ) {
530                 DBGC ( tftp, "TFTP %p received packet without metadata\n",
531                        tftp );
532                 goto done;
533         }
534         if ( ! meta->src ) {
535                 DBGC ( tftp, "TFTP %p received packet without source port\n",
536                        tftp );
537                 goto done;
538         }
539
540         /* Filter by TID.  Set TID on first response received */
541         st_src = ( struct sockaddr_tcpip * ) meta->src;
542         if ( tftp->state < 0 ) {
543                 memcpy ( &tftp->peer, st_src, sizeof ( tftp->peer ) );
544                 DBGC ( tftp, "TFTP %p using remote port %d\n", tftp,
545                        ntohs ( tftp->peer.st_port ) );
546         } else if ( memcmp ( &tftp->peer, st_src,
547                              sizeof ( tftp->peer ) ) != 0 ) {
548                 DBGC ( tftp, "TFTP %p received packet from wrong source (got "
549                        "%d, wanted %d)\n", tftp, ntohs ( st_src->st_port ),
550                        ntohs ( tftp->peer.st_port ) );
551                 goto done;
552         }
553
554         switch ( common->opcode ) {
555         case htons ( TFTP_OACK ):
556                 rc = tftp_rx_oack ( tftp, iobuf->data, len );
557                 break;
558         case htons ( TFTP_DATA ):
559                 rc = tftp_rx_data ( tftp, iobuf );
560                 iobuf = NULL;
561                 break;
562         case htons ( TFTP_ERROR ):
563                 rc = tftp_rx_error ( tftp, iobuf->data, len );
564                 break;
565         default:
566                 DBGC ( tftp, "TFTP %p received strange packet type %d\n",
567                        tftp, ntohs ( common->opcode ) );
568                 break;
569         };
570
571  done:
572         free_iob ( iobuf );
573         return rc;
574 }
575
576 /**
577  * TFTP connection closed by network stack
578  *
579  * @v socket            Transport layer interface
580  * @v rc                Reason for close
581  */
582 static void tftp_socket_close ( struct xfer_interface *socket, int rc ) {
583         struct tftp_request *tftp =
584                 container_of ( socket, struct tftp_request, socket );
585
586         DBGC ( tftp, "TFTP %p socket closed: %s\n",
587                tftp, strerror ( rc ) );
588
589         tftp_done ( tftp, rc );
590 }
591
592 /** TFTP socket operations */
593 static struct xfer_interface_operations tftp_socket_operations = {
594         .close          = tftp_socket_close,
595         .vredirect      = xfer_vopen,
596         .seek           = ignore_xfer_seek,
597         .window         = unlimited_xfer_window,
598         .alloc_iob      = default_xfer_alloc_iob,
599         .deliver_iob    = tftp_socket_deliver_iob,
600         .deliver_raw    = xfer_deliver_as_iob,
601 };
602  
603 /**
604  * Close TFTP data transfer interface
605  *
606  * @v xfer              Data transfer interface
607  * @v rc                Reason for close
608  */
609 static void tftp_xfer_close ( struct xfer_interface *xfer, int rc ) {
610         struct tftp_request *tftp =
611                 container_of ( xfer, struct tftp_request, xfer );
612
613         DBGC ( tftp, "TFTP %p interface closed: %s\n",
614                tftp, strerror ( rc ) );
615
616         tftp_done ( tftp, rc );
617 }
618
619 /** TFTP data transfer interface operations */
620 static struct xfer_interface_operations tftp_xfer_operations = {
621         .close          = tftp_xfer_close,
622         .vredirect      = ignore_xfer_vredirect,
623         .seek           = ignore_xfer_seek,
624         .window         = unlimited_xfer_window,
625         .alloc_iob      = default_xfer_alloc_iob,
626         .deliver_iob    = xfer_deliver_as_raw,
627         .deliver_raw    = ignore_xfer_deliver_raw,
628 };
629
630 /**
631  * Initiate TFTP download
632  *
633  * @v xfer              Data transfer interface
634  * @v uri               Uniform Resource Identifier
635  * @ret rc              Return status code
636  */
637 int tftp_open ( struct xfer_interface *xfer, struct uri *uri ) {
638         struct tftp_request *tftp;
639         struct sockaddr_tcpip server;
640         int rc;
641
642         /* Sanity checks */
643         if ( ! uri->host )
644                 return -EINVAL;
645         if ( ! uri->path )
646                 return -EINVAL;
647
648         /* Allocate and populate TFTP structure */
649         tftp = zalloc ( sizeof ( *tftp ) );
650         if ( ! tftp )
651                 return -ENOMEM;
652         tftp->refcnt.free = tftp_free;
653         xfer_init ( &tftp->xfer, &tftp_xfer_operations, &tftp->refcnt );
654         tftp->uri = uri_get ( uri );
655         xfer_init ( &tftp->socket, &tftp_socket_operations, &tftp->refcnt );
656         tftp->blksize = TFTP_DEFAULT_BLKSIZE;
657         tftp->state = -1;
658         tftp->timer.expired = tftp_timer_expired;
659
660         /* Open socket */
661         memset ( &server, 0, sizeof ( server ) );
662         server.st_port = htons ( uri_port ( tftp->uri, TFTP_PORT ) );
663         if ( ( rc = xfer_open_named_socket ( &tftp->socket, SOCK_DGRAM,
664                                              ( struct sockaddr * ) &server,
665                                              uri->host, NULL ) ) != 0 )
666                 goto err;
667
668         /* Start timer to initiate RRQ */
669         start_timer_nodelay ( &tftp->timer );
670
671         /* Attach to parent interface, mortalise self, and return */
672         xfer_plug_plug ( &tftp->xfer, xfer );
673         ref_put ( &tftp->refcnt );
674         return 0;
675
676  err:
677         DBGC ( tftp, "TFTP %p could not create request: %s\n",
678                tftp, strerror ( rc ) );
679         tftp_done ( tftp, rc );
680         ref_put ( &tftp->refcnt );
681         return rc;
682 }
683
684 /** TFTP URI opener */
685 struct uri_opener tftp_uri_opener __uri_opener = {
686         .scheme = "tftp",
687         .open   = tftp_open,
688 };