2 * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
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.
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.
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.
27 #include <gpxe/refcnt.h>
28 #include <gpxe/xfer.h>
29 #include <gpxe/open.h>
31 #include <gpxe/tcpip.h>
32 #include <gpxe/retry.h>
33 #include <gpxe/features.h>
34 #include <gpxe/bitmap.h>
35 #include <gpxe/settings.h>
36 #include <gpxe/dhcp.h>
38 #include <gpxe/tftp.h>
46 FEATURE ( FEATURE_PROTOCOL, "TFTP", DHCP_EB_FEATURE_TFTP, 1 );
51 * This data structure holds the state for an ongoing TFTP transfer.
54 /** Reference count */
56 /** Data transfer interface */
57 struct xfer_interface xfer;
59 /** URI being fetched */
61 /** Transport layer interface */
62 struct xfer_interface socket;
63 /** Multicast transport layer interface */
64 struct xfer_interface mc_socket;
68 * This is the "blksize" option negotiated with the TFTP
69 * server. (If the TFTP server does not support TFTP options,
70 * this will default to 512).
75 * This is the value returned in the "tsize" option from the
76 * TFTP server. If the TFTP server does not support the
77 * "tsize" option, this value will be zero.
83 * This is the port to which RRQ packets are sent.
88 * The peer address is determined by the first response
89 * received to the TFTP RRQ.
91 struct sockaddr_tcpip peer;
94 /** MTFTP timeout count */
95 unsigned int mtftp_timeouts;
99 /** Maximum known length
101 * We don't always know the file length in advance. In
102 * particular, if the TFTP server doesn't support the tsize
103 * option, or we are using MTFTP, then we don't know the file
104 * length until we see the end-of-file block (which, in the
105 * case of MTFTP, may not be the last block we see).
107 * This value is updated whenever we obtain information about
111 /** Retransmission timer */
112 struct retry_timer timer;
115 /** TFTP request flags */
117 /** Send ACK packets */
118 TFTP_FL_SEND_ACK = 0x0001,
119 /** Request blksize and tsize options */
120 TFTP_FL_RRQ_SIZES = 0x0002,
121 /** Request multicast option */
122 TFTP_FL_RRQ_MULTICAST = 0x0004,
123 /** Perform MTFTP recovery on timeout */
124 TFTP_FL_MTFTP_RECOVERY = 0x0008,
127 /** Maximum number of MTFTP open requests before falling back to TFTP */
128 #define MTFTP_MAX_TIMEOUTS 3
133 * @v refcnt Reference counter
135 static void tftp_free ( struct refcnt *refcnt ) {
136 struct tftp_request *tftp =
137 container_of ( refcnt, struct tftp_request, refcnt );
139 uri_put ( tftp->uri );
140 bitmap_free ( &tftp->bitmap );
145 * Mark TFTP request as complete
147 * @v tftp TFTP connection
148 * @v rc Return status code
150 static void tftp_done ( struct tftp_request *tftp, int rc ) {
152 DBGC ( tftp, "TFTP %p finished with status %d (%s)\n",
153 tftp, rc, strerror ( rc ) );
155 /* Stop the retry timer */
156 stop_timer ( &tftp->timer );
158 /* Close all data transfer interfaces */
159 xfer_nullify ( &tftp->socket );
160 xfer_close ( &tftp->socket, rc );
161 xfer_nullify ( &tftp->mc_socket );
162 xfer_close ( &tftp->mc_socket, rc );
163 xfer_nullify ( &tftp->xfer );
164 xfer_close ( &tftp->xfer, rc );
170 * @v tftp TFTP connection
171 * @ret rc Return status code
173 static int tftp_reopen ( struct tftp_request *tftp ) {
174 struct sockaddr_tcpip server;
178 xfer_close ( &tftp->socket, 0 );
180 /* Disable ACK sending. */
181 tftp->flags &= ~TFTP_FL_SEND_ACK;
183 /* Reset peer address */
184 memset ( &tftp->peer, 0, sizeof ( tftp->peer ) );
187 memset ( &server, 0, sizeof ( server ) );
188 server.st_port = htons ( tftp->port );
189 if ( ( rc = xfer_open_named_socket ( &tftp->socket, SOCK_DGRAM,
190 ( struct sockaddr * ) &server,
191 tftp->uri->host, NULL ) ) != 0 ) {
192 DBGC ( tftp, "TFTP %p could not open socket: %s\n",
193 tftp, strerror ( rc ) );
201 * Reopen TFTP multicast socket
203 * @v tftp TFTP connection
204 * @v local Local socket address
205 * @ret rc Return status code
207 static int tftp_reopen_mc ( struct tftp_request *tftp,
208 struct sockaddr *local ) {
211 /* Close multicast socket */
212 xfer_close ( &tftp->mc_socket, 0 );
214 /* Open multicast socket. We never send via this socket, so
215 * use the local address as the peer address (since the peer
216 * address cannot be NULL).
218 if ( ( rc = xfer_open_socket ( &tftp->mc_socket, SOCK_DGRAM,
219 local, local ) ) != 0 ) {
220 DBGC ( tftp, "TFTP %p could not open multicast "
221 "socket: %s\n", tftp, strerror ( rc ) );
229 * Presize TFTP receive buffers and block bitmap
231 * @v tftp TFTP connection
232 * @v filesize Known minimum file size
233 * @ret rc Return status code
235 static int tftp_presize ( struct tftp_request *tftp, size_t filesize ) {
236 unsigned int num_blocks;
239 /* Do nothing if we are already large enough */
240 if ( filesize <= tftp->filesize )
243 /* Record filesize */
244 tftp->filesize = filesize;
246 /* Notify recipient of file size */
247 xfer_seek ( &tftp->xfer, filesize, SEEK_SET );
248 xfer_seek ( &tftp->xfer, 0, SEEK_SET );
250 /* Calculate expected number of blocks. Note that files whose
251 * length is an exact multiple of the blocksize will have a
252 * trailing zero-length block, which must be included.
254 num_blocks = ( ( filesize / tftp->blksize ) + 1 );
255 if ( ( rc = bitmap_resize ( &tftp->bitmap, num_blocks ) ) != 0 ) {
256 DBGC ( tftp, "TFTP %p could not resize bitmap to %d blocks: "
257 "%s\n", tftp, num_blocks, strerror ( rc ) );
265 * TFTP requested blocksize
267 * This is treated as a global configuration parameter.
269 static unsigned int tftp_request_blksize = TFTP_MAX_BLKSIZE;
272 * Set TFTP request blocksize
274 * @v blksize Requested block size
276 void tftp_set_request_blksize ( unsigned int blksize ) {
277 if ( blksize < TFTP_DEFAULT_BLKSIZE )
278 blksize = TFTP_DEFAULT_BLKSIZE;
279 tftp_request_blksize = blksize;
283 * MTFTP multicast receive address
285 * This is treated as a global configuration parameter.
287 static struct sockaddr_in tftp_mtftp_socket = {
288 .sin_family = AF_INET,
289 .sin_addr.s_addr = htonl ( 0xefff0101 ),
290 .sin_port = htons ( 3001 ),
294 * Set MTFTP multicast address
296 * @v address Multicast IPv4 address
298 void tftp_set_mtftp_address ( struct in_addr address ) {
299 tftp_mtftp_socket.sin_addr = address;
303 * Set MTFTP multicast port
305 * @v port Multicast port
307 void tftp_set_mtftp_port ( unsigned int port ) {
308 tftp_mtftp_socket.sin_port = htons ( port );
314 * @v tftp TFTP connection
315 * @ret rc Return status code
317 static int tftp_send_rrq ( struct tftp_request *tftp ) {
318 struct tftp_rrq *rrq;
319 const char *path = tftp->uri->path;
320 size_t len = ( sizeof ( *rrq ) + strlen ( path ) + 1 /* NUL */
321 + 5 + 1 /* "octet" + NUL */
322 + 7 + 1 + 5 + 1 /* "blksize" + NUL + ddddd + NUL */
323 + 5 + 1 + 1 + 1 /* "tsize" + NUL + "0" + NUL */
324 + 9 + 1 + 1 /* "multicast" + NUL + NUL */ );
325 struct io_buffer *iobuf;
327 DBGC ( tftp, "TFTP %p requesting \"%s\"\n", tftp, path );
329 /* Allocate buffer */
330 iobuf = xfer_alloc_iob ( &tftp->socket, len );
335 rrq = iob_put ( iobuf, sizeof ( *rrq ) );
336 rrq->opcode = htons ( TFTP_RRQ );
337 iob_put ( iobuf, snprintf ( iobuf->tail, iob_tailroom ( iobuf ),
338 "%s%coctet", path, 0 ) + 1 );
339 if ( tftp->flags & TFTP_FL_RRQ_SIZES ) {
340 iob_put ( iobuf, snprintf ( iobuf->tail,
341 iob_tailroom ( iobuf ),
342 "blksize%c%d%ctsize%c0", 0,
343 tftp_request_blksize, 0, 0 ) + 1 );
345 if ( tftp->flags & TFTP_FL_RRQ_MULTICAST ) {
346 iob_put ( iobuf, snprintf ( iobuf->tail,
347 iob_tailroom ( iobuf ),
348 "multicast%c", 0 ) + 1 );
351 /* RRQ always goes to the address specified in the initial
354 return xfer_deliver_iob ( &tftp->socket, iobuf );
360 * @v tftp TFTP connection
361 * @ret rc Return status code
363 static int tftp_send_ack ( struct tftp_request *tftp ) {
364 struct tftp_ack *ack;
365 struct io_buffer *iobuf;
366 struct xfer_metadata meta = {
367 .dest = ( struct sockaddr * ) &tftp->peer,
371 /* Determine next required block number */
372 block = bitmap_first_gap ( &tftp->bitmap );
373 DBGC2 ( tftp, "TFTP %p sending ACK for block %d\n", tftp, block );
375 /* Allocate buffer */
376 iobuf = xfer_alloc_iob ( &tftp->socket, sizeof ( *ack ) );
381 ack = iob_put ( iobuf, sizeof ( *ack ) );
382 ack->opcode = htons ( TFTP_ACK );
383 ack->block = htons ( block );
385 /* ACK always goes to the peer recorded from the RRQ response */
386 return xfer_deliver_iob_meta ( &tftp->socket, iobuf, &meta );
390 * Transmit next relevant packet
392 * @v tftp TFTP connection
393 * @ret rc Return status code
395 static int tftp_send_packet ( struct tftp_request *tftp ) {
397 /* Update retransmission timer */
398 stop_timer ( &tftp->timer );
399 start_timer ( &tftp->timer );
401 /* Send RRQ or ACK as appropriate */
402 if ( ! tftp->peer.st_family ) {
403 return tftp_send_rrq ( tftp );
405 if ( tftp->flags & TFTP_FL_SEND_ACK ) {
406 return tftp_send_ack ( tftp );
414 * Handle TFTP retransmission timer expiry
416 * @v timer Retry timer
417 * @v fail Failure indicator
419 static void tftp_timer_expired ( struct retry_timer *timer, int fail ) {
420 struct tftp_request *tftp =
421 container_of ( timer, struct tftp_request, timer );
424 /* If we are doing MTFTP, attempt the various recovery strategies */
425 if ( tftp->flags & TFTP_FL_MTFTP_RECOVERY ) {
426 if ( tftp->peer.st_family ) {
427 /* If we have received any response from the server,
428 * try resending the RRQ to restart the download.
430 DBGC ( tftp, "TFTP %p attempting reopen\n", tftp );
431 if ( ( rc = tftp_reopen ( tftp ) ) != 0 )
434 /* Fall back to plain TFTP after several attempts */
435 tftp->mtftp_timeouts++;
436 DBGC ( tftp, "TFTP %p timeout %d waiting for MTFTP "
437 "open\n", tftp, tftp->mtftp_timeouts );
439 if ( tftp->mtftp_timeouts > MTFTP_MAX_TIMEOUTS ) {
440 DBGC ( tftp, "TFTP %p falling back to plain "
442 tftp->flags = TFTP_FL_RRQ_SIZES;
444 /* Close multicast socket */
445 xfer_close ( &tftp->mc_socket, 0 );
447 /* Reset retry timer */
448 start_timer_nodelay ( &tftp->timer );
450 /* The blocksize may change: discard
453 bitmap_free ( &tftp->bitmap );
454 memset ( &tftp->bitmap, 0,
455 sizeof ( tftp->bitmap ) );
457 /* Reopen on standard TFTP port */
458 tftp->port = TFTP_PORT;
459 if ( ( rc = tftp_reopen ( tftp ) ) != 0 )
464 /* Not doing MTFTP (or have fallen back to plain
465 * TFTP); fail as per normal.
472 tftp_send_packet ( tftp );
476 tftp_done ( tftp, rc );
480 * Process TFTP "blksize" option
482 * @v tftp TFTP connection
483 * @v value Option value
484 * @ret rc Return status code
486 static int tftp_process_blksize ( struct tftp_request *tftp,
487 const char *value ) {
490 tftp->blksize = strtoul ( value, &end, 10 );
492 DBGC ( tftp, "TFTP %p got invalid blksize \"%s\"\n",
496 DBGC ( tftp, "TFTP %p blksize=%d\n", tftp, tftp->blksize );
502 * Process TFTP "tsize" option
504 * @v tftp TFTP connection
505 * @v value Option value
506 * @ret rc Return status code
508 static int tftp_process_tsize ( struct tftp_request *tftp,
509 const char *value ) {
512 tftp->tsize = strtoul ( value, &end, 10 );
514 DBGC ( tftp, "TFTP %p got invalid tsize \"%s\"\n",
518 DBGC ( tftp, "TFTP %p tsize=%ld\n", tftp, tftp->tsize );
524 * Process TFTP "multicast" option
526 * @v tftp TFTP connection
527 * @v value Option value
528 * @ret rc Return status code
530 static int tftp_process_multicast ( struct tftp_request *tftp,
531 const char *value ) {
534 struct sockaddr_in sin;
536 char buf[ strlen ( value ) + 1 ];
544 /* Split value into "addr,port,mc" fields */
545 memcpy ( buf, value, sizeof ( buf ) );
547 port = strchr ( addr, ',' );
549 DBGC ( tftp, "TFTP %p multicast missing port,mc\n", tftp );
553 mc = strchr ( port, ',' );
555 DBGC ( tftp, "TFTP %p multicast missing mc\n", tftp );
560 /* Parse parameters */
561 if ( strtoul ( mc, &mc_end, 0 ) == 0 )
562 tftp->flags &= ~TFTP_FL_SEND_ACK;
564 DBGC ( tftp, "TFTP %p multicast invalid mc %s\n", tftp, mc );
567 DBGC ( tftp, "TFTP %p is%s the master client\n",
568 tftp, ( ( tftp->flags & TFTP_FL_SEND_ACK ) ? "" : " not" ) );
569 if ( *addr && *port ) {
570 socket.sin.sin_family = AF_INET;
571 if ( inet_aton ( addr, &socket.sin.sin_addr ) == 0 ) {
572 DBGC ( tftp, "TFTP %p multicast invalid IP address "
573 "%s\n", tftp, addr );
576 DBGC ( tftp, "TFTP %p multicast IP address %s\n",
577 tftp, inet_ntoa ( socket.sin.sin_addr ) );
578 socket.sin.sin_port = htons ( strtoul ( port, &port_end, 0 ) );
580 DBGC ( tftp, "TFTP %p multicast invalid port %s\n",
584 DBGC ( tftp, "TFTP %p multicast port %d\n",
585 tftp, ntohs ( socket.sin.sin_port ) );
586 if ( ( rc = tftp_reopen_mc ( tftp, &socket.sa ) ) != 0 )
599 * @v tftp TFTP connection
600 * @v value Option value
601 * @ret rc Return status code
603 int ( * process ) ( struct tftp_request *tftp, const char *value );
606 /** Recognised TFTP options */
607 static struct tftp_option tftp_options[] = {
608 { "blksize", tftp_process_blksize },
609 { "tsize", tftp_process_tsize },
610 { "multicast", tftp_process_multicast },
615 * Process TFTP option
617 * @v tftp TFTP connection
618 * @v name Option name
619 * @v value Option value
620 * @ret rc Return status code
622 static int tftp_process_option ( struct tftp_request *tftp,
623 const char *name, const char *value ) {
624 struct tftp_option *option;
626 for ( option = tftp_options ; option->name ; option++ ) {
627 if ( strcasecmp ( name, option->name ) == 0 )
628 return option->process ( tftp, value );
631 DBGC ( tftp, "TFTP %p received unknown option \"%s\" = \"%s\"\n",
634 /* Unknown options should be silently ignored */
641 * @v tftp TFTP connection
642 * @v buf Temporary data buffer
643 * @v len Length of temporary data buffer
644 * @ret rc Return status code
646 static int tftp_rx_oack ( struct tftp_request *tftp, void *buf, size_t len ) {
647 struct tftp_oack *oack = buf;
648 char *end = buf + len;
654 if ( len < sizeof ( *oack ) ) {
655 DBGC ( tftp, "TFTP %p received underlength OACK packet "
656 "length %zd\n", tftp, len );
660 if ( end[-1] != '\0' ) {
661 DBGC ( tftp, "TFTP %p received OACK missing final NUL\n",
667 /* Process each option in turn */
669 while ( name < end ) {
670 value = ( name + strlen ( name ) + 1 );
671 if ( value == end ) {
672 DBGC ( tftp, "TFTP %p received OACK missing value "
673 "for option \"%s\"\n", tftp, name );
677 if ( ( rc = tftp_process_option ( tftp, name, value ) ) != 0 )
679 name = ( value + strlen ( value ) + 1 );
682 /* Process tsize information, if available */
684 if ( ( rc = tftp_presize ( tftp, tftp->tsize ) ) != 0 )
688 /* Request next data block */
689 tftp_send_packet ( tftp );
693 tftp_done ( tftp, rc );
700 * @v tftp TFTP connection
701 * @v iobuf I/O buffer
702 * @ret rc Return status code
704 * Takes ownership of I/O buffer.
706 static int tftp_rx_data ( struct tftp_request *tftp,
707 struct io_buffer *iobuf ) {
708 struct tftp_data *data = iobuf->data;
709 struct xfer_metadata meta;
716 if ( iob_len ( iobuf ) < sizeof ( *data ) ) {
717 DBGC ( tftp, "TFTP %p received underlength DATA packet "
718 "length %zd\n", tftp, iob_len ( iobuf ) );
724 block = ( ntohs ( data->block ) - 1 );
725 offset = ( block * tftp->blksize );
726 iob_pull ( iobuf, sizeof ( *data ) );
727 data_len = iob_len ( iobuf );
728 if ( data_len > tftp->blksize ) {
729 DBGC ( tftp, "TFTP %p received overlength DATA packet "
730 "length %zd\n", tftp, data_len );
736 memset ( &meta, 0, sizeof ( meta ) );
737 meta.whence = SEEK_SET;
738 meta.offset = offset;
739 rc = xfer_deliver_iob_meta ( &tftp->xfer, iobuf, &meta );
742 DBGC ( tftp, "TFTP %p could not deliver data: %s\n",
743 tftp, strerror ( rc ) );
747 /* Ensure block bitmap is ready */
748 if ( ( rc = tftp_presize ( tftp, ( offset + data_len ) ) ) != 0 )
751 /* Mark block as received */
752 bitmap_set ( &tftp->bitmap, block );
754 /* Acknowledge block */
755 tftp_send_packet ( tftp );
757 /* If all blocks have been received, finish. */
758 if ( bitmap_full ( &tftp->bitmap ) )
759 tftp_done ( tftp, 0 );
764 tftp_done ( tftp, rc );
768 /** Translation between TFTP errors and internal error numbers */
769 static const int tftp_errors[] = {
770 [TFTP_ERR_FILE_NOT_FOUND] = ENOENT,
771 [TFTP_ERR_ACCESS_DENIED] = EACCES,
772 [TFTP_ERR_ILLEGAL_OP] = ENOTSUP,
778 * @v tftp TFTP connection
779 * @v buf Temporary data buffer
780 * @v len Length of temporary data buffer
781 * @ret rc Return status code
783 static int tftp_rx_error ( struct tftp_request *tftp, void *buf, size_t len ) {
784 struct tftp_error *error = buf;
789 if ( len < sizeof ( *error ) ) {
790 DBGC ( tftp, "TFTP %p received underlength ERROR packet "
791 "length %zd\n", tftp, len );
795 DBGC ( tftp, "TFTP %p received ERROR packet with code %d, message "
796 "\"%s\"\n", tftp, ntohs ( error->errcode ), error->errmsg );
798 /* Determine final operation result */
799 err = ntohs ( error->errcode );
800 if ( err < ( sizeof ( tftp_errors ) / sizeof ( tftp_errors[0] ) ) )
801 rc = -tftp_errors[err];
805 /* Close TFTP request */
806 tftp_done ( tftp, rc );
814 * @v tftp TFTP connection
815 * @v iobuf I/O buffer
816 * @v meta Transfer metadata, or NULL
817 * @ret rc Return status code
819 static int tftp_rx ( struct tftp_request *tftp,
820 struct io_buffer *iobuf,
821 struct xfer_metadata *meta ) {
822 struct sockaddr_tcpip *st_src;
823 struct tftp_common *common = iobuf->data;
824 size_t len = iob_len ( iobuf );
828 if ( len < sizeof ( *common ) ) {
829 DBGC ( tftp, "TFTP %p received underlength packet length "
830 "%zd\n", tftp, len );
834 DBGC ( tftp, "TFTP %p received packet without metadata\n",
839 DBGC ( tftp, "TFTP %p received packet without source port\n",
844 /* Filter by TID. Set TID on first response received */
845 st_src = ( struct sockaddr_tcpip * ) meta->src;
846 if ( ! tftp->peer.st_family ) {
847 memcpy ( &tftp->peer, st_src, sizeof ( tftp->peer ) );
848 DBGC ( tftp, "TFTP %p using remote port %d\n", tftp,
849 ntohs ( tftp->peer.st_port ) );
850 } else if ( memcmp ( &tftp->peer, st_src,
851 sizeof ( tftp->peer ) ) != 0 ) {
852 DBGC ( tftp, "TFTP %p received packet from wrong source (got "
853 "%d, wanted %d)\n", tftp, ntohs ( st_src->st_port ),
854 ntohs ( tftp->peer.st_port ) );
858 switch ( common->opcode ) {
859 case htons ( TFTP_OACK ):
860 rc = tftp_rx_oack ( tftp, iobuf->data, len );
862 case htons ( TFTP_DATA ):
863 rc = tftp_rx_data ( tftp, iobuf );
866 case htons ( TFTP_ERROR ):
867 rc = tftp_rx_error ( tftp, iobuf->data, len );
870 DBGC ( tftp, "TFTP %p received strange packet type %d\n",
871 tftp, ntohs ( common->opcode ) );
881 * Receive new data via socket
883 * @v socket Transport layer interface
884 * @v iobuf I/O buffer
885 * @v meta Transfer metadata, or NULL
886 * @ret rc Return status code
888 static int tftp_socket_deliver_iob ( struct xfer_interface *socket,
889 struct io_buffer *iobuf,
890 struct xfer_metadata *meta ) {
891 struct tftp_request *tftp =
892 container_of ( socket, struct tftp_request, socket );
894 /* Enable sending ACKs when we receive a unicast packet. This
895 * covers three cases:
897 * 1. Standard TFTP; we should always send ACKs, and will
898 * always receive a unicast packet before we need to send the
901 * 2. RFC2090 multicast TFTP; the only unicast packets we will
902 * receive are the OACKs; enable sending ACKs here (before
903 * processing the OACK) and disable it when processing the
904 * multicast option if we are not the master client.
906 * 3. MTFTP; receiving a unicast datagram indicates that we
907 * are the "master client" and should send ACKs.
909 tftp->flags |= TFTP_FL_SEND_ACK;
911 return tftp_rx ( tftp, iobuf, meta );
914 /** TFTP socket operations */
915 static struct xfer_interface_operations tftp_socket_operations = {
916 .close = ignore_xfer_close,
917 .vredirect = xfer_vopen,
918 .window = unlimited_xfer_window,
919 .alloc_iob = default_xfer_alloc_iob,
920 .deliver_iob = tftp_socket_deliver_iob,
921 .deliver_raw = xfer_deliver_as_iob,
925 * Receive new data via multicast socket
927 * @v mc_socket Multicast transport layer interface
928 * @v iobuf I/O buffer
929 * @v meta Transfer metadata, or NULL
930 * @ret rc Return status code
932 static int tftp_mc_socket_deliver_iob ( struct xfer_interface *mc_socket,
933 struct io_buffer *iobuf,
934 struct xfer_metadata *meta ) {
935 struct tftp_request *tftp =
936 container_of ( mc_socket, struct tftp_request, mc_socket );
938 return tftp_rx ( tftp, iobuf, meta );
941 /** TFTP multicast socket operations */
942 static struct xfer_interface_operations tftp_mc_socket_operations = {
943 .close = ignore_xfer_close,
944 .vredirect = xfer_vopen,
945 .window = unlimited_xfer_window,
946 .alloc_iob = default_xfer_alloc_iob,
947 .deliver_iob = tftp_mc_socket_deliver_iob,
948 .deliver_raw = xfer_deliver_as_iob,
952 * Close TFTP data transfer interface
954 * @v xfer Data transfer interface
955 * @v rc Reason for close
957 static void tftp_xfer_close ( struct xfer_interface *xfer, int rc ) {
958 struct tftp_request *tftp =
959 container_of ( xfer, struct tftp_request, xfer );
961 DBGC ( tftp, "TFTP %p interface closed: %s\n",
962 tftp, strerror ( rc ) );
964 tftp_done ( tftp, rc );
967 /** TFTP data transfer interface operations */
968 static struct xfer_interface_operations tftp_xfer_operations = {
969 .close = tftp_xfer_close,
970 .vredirect = ignore_xfer_vredirect,
971 .window = unlimited_xfer_window,
972 .alloc_iob = default_xfer_alloc_iob,
973 .deliver_iob = xfer_deliver_as_raw,
974 .deliver_raw = ignore_xfer_deliver_raw,
978 * Initiate TFTP/TFTM/MTFTP download
980 * @v xfer Data transfer interface
981 * @v uri Uniform Resource Identifier
982 * @ret rc Return status code
984 static int tftp_core_open ( struct xfer_interface *xfer, struct uri *uri,
985 unsigned int default_port,
986 struct sockaddr *multicast,
987 unsigned int flags ) {
988 struct tftp_request *tftp;
997 /* Allocate and populate TFTP structure */
998 tftp = zalloc ( sizeof ( *tftp ) );
1001 tftp->refcnt.free = tftp_free;
1002 xfer_init ( &tftp->xfer, &tftp_xfer_operations, &tftp->refcnt );
1003 tftp->uri = uri_get ( uri );
1004 xfer_init ( &tftp->socket, &tftp_socket_operations, &tftp->refcnt );
1005 xfer_init ( &tftp->mc_socket, &tftp_mc_socket_operations,
1007 tftp->blksize = TFTP_DEFAULT_BLKSIZE;
1008 tftp->flags = flags;
1009 tftp->timer.expired = tftp_timer_expired;
1012 tftp->port = uri_port ( tftp->uri, default_port );
1013 if ( ( rc = tftp_reopen ( tftp ) ) != 0 )
1016 /* Open multicast socket */
1018 if ( ( rc = tftp_reopen_mc ( tftp, multicast ) ) != 0 )
1022 /* Start timer to initiate RRQ */
1023 start_timer_nodelay ( &tftp->timer );
1025 /* Attach to parent interface, mortalise self, and return */
1026 xfer_plug_plug ( &tftp->xfer, xfer );
1027 ref_put ( &tftp->refcnt );
1031 DBGC ( tftp, "TFTP %p could not create request: %s\n",
1032 tftp, strerror ( rc ) );
1033 tftp_done ( tftp, rc );
1034 ref_put ( &tftp->refcnt );
1039 * Initiate TFTP download
1041 * @v xfer Data transfer interface
1042 * @v uri Uniform Resource Identifier
1043 * @ret rc Return status code
1045 static int tftp_open ( struct xfer_interface *xfer, struct uri *uri ) {
1046 return tftp_core_open ( xfer, uri, TFTP_PORT, NULL,
1047 TFTP_FL_RRQ_SIZES );
1051 /** TFTP URI opener */
1052 struct uri_opener tftp_uri_opener __uri_opener = {
1058 * Initiate TFTM download
1060 * @v xfer Data transfer interface
1061 * @v uri Uniform Resource Identifier
1062 * @ret rc Return status code
1064 static int tftm_open ( struct xfer_interface *xfer, struct uri *uri ) {
1065 return tftp_core_open ( xfer, uri, TFTP_PORT, NULL,
1066 ( TFTP_FL_RRQ_SIZES |
1067 TFTP_FL_RRQ_MULTICAST ) );
1071 /** TFTM URI opener */
1072 struct uri_opener tftm_uri_opener __uri_opener = {
1078 * Initiate MTFTP download
1080 * @v xfer Data transfer interface
1081 * @v uri Uniform Resource Identifier
1082 * @ret rc Return status code
1084 static int mtftp_open ( struct xfer_interface *xfer, struct uri *uri ) {
1085 return tftp_core_open ( xfer, uri, MTFTP_PORT,
1086 ( struct sockaddr * ) &tftp_mtftp_socket,
1087 TFTP_FL_MTFTP_RECOVERY );
1090 /** MTFTP URI opener */
1091 struct uri_opener mtftp_uri_opener __uri_opener = {
1096 /******************************************************************************
1100 ******************************************************************************
1103 /** TFTP server setting */
1104 struct setting next_server_setting __setting = {
1105 .name = "next-server",
1106 .description = "TFTP server",
1107 .tag = DHCP_EB_SIADDR,
1108 .type = &setting_type_ipv4,
1112 * Apply TFTP configuration settings
1114 * @ret rc Return status code
1116 static int tftp_apply_settings ( void ) {
1117 static struct in_addr tftp_server = { 0 };
1118 struct in_addr last_tftp_server;
1119 char uri_string[32];
1122 /* Retrieve TFTP server setting */
1123 last_tftp_server = tftp_server;
1124 fetch_ipv4_setting ( NULL, &next_server_setting, &tftp_server );
1126 /* If TFTP server setting has changed, set the current working
1127 * URI to match. Do it only when the TFTP server has changed
1128 * to try to minimise surprises to the user, who probably
1129 * won't expect the CWURI to change just because they updated
1130 * an unrelated setting and triggered all the settings
1133 if ( tftp_server.s_addr != last_tftp_server.s_addr ) {
1134 snprintf ( uri_string, sizeof ( uri_string ),
1135 "tftp://%s/", inet_ntoa ( tftp_server ) );
1136 uri = parse_uri ( uri_string );
1146 /** TFTP settings applicator */
1147 struct settings_applicator tftp_settings_applicator __settings_applicator = {
1148 .apply = tftp_apply_settings,