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