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;
321 struct io_buffer *iobuf;
323 /* Strip initial '/' if present. If we were opened via the
324 * URI interface, then there will be an initial '/', since a
325 * full tftp:// URI provides no way to specify a non-absolute
326 * path. However, many TFTP servers (particularly Windows
327 * TFTP servers) complain about having an initial '/', and it
328 * violates user expectations to have a '/' silently added to
329 * the DHCP-specified filename.
331 path = tftp->uri->path;
335 DBGC ( tftp, "TFTP %p requesting \"%s\"\n", tftp, path );
337 /* Allocate buffer */
338 len = ( sizeof ( *rrq ) + strlen ( path ) + 1 /* NUL */
339 + 5 + 1 /* "octet" + NUL */
340 + 7 + 1 + 5 + 1 /* "blksize" + NUL + ddddd + NUL */
341 + 5 + 1 + 1 + 1 /* "tsize" + NUL + "0" + NUL */
342 + 9 + 1 + 1 /* "multicast" + NUL + NUL */ );
343 iobuf = xfer_alloc_iob ( &tftp->socket, len );
348 rrq = iob_put ( iobuf, sizeof ( *rrq ) );
349 rrq->opcode = htons ( TFTP_RRQ );
350 iob_put ( iobuf, snprintf ( iobuf->tail, iob_tailroom ( iobuf ),
351 "%s%coctet", path, 0 ) + 1 );
352 if ( tftp->flags & TFTP_FL_RRQ_SIZES ) {
353 iob_put ( iobuf, snprintf ( iobuf->tail,
354 iob_tailroom ( iobuf ),
355 "blksize%c%d%ctsize%c0", 0,
356 tftp_request_blksize, 0, 0 ) + 1 );
358 if ( tftp->flags & TFTP_FL_RRQ_MULTICAST ) {
359 iob_put ( iobuf, snprintf ( iobuf->tail,
360 iob_tailroom ( iobuf ),
361 "multicast%c", 0 ) + 1 );
364 /* RRQ always goes to the address specified in the initial
367 return xfer_deliver_iob ( &tftp->socket, iobuf );
373 * @v tftp TFTP connection
374 * @ret rc Return status code
376 static int tftp_send_ack ( struct tftp_request *tftp ) {
377 struct tftp_ack *ack;
378 struct io_buffer *iobuf;
379 struct xfer_metadata meta = {
380 .dest = ( struct sockaddr * ) &tftp->peer,
384 /* Determine next required block number */
385 block = bitmap_first_gap ( &tftp->bitmap );
386 DBGC2 ( tftp, "TFTP %p sending ACK for block %d\n", tftp, block );
388 /* Allocate buffer */
389 iobuf = xfer_alloc_iob ( &tftp->socket, sizeof ( *ack ) );
394 ack = iob_put ( iobuf, sizeof ( *ack ) );
395 ack->opcode = htons ( TFTP_ACK );
396 ack->block = htons ( block );
398 /* ACK always goes to the peer recorded from the RRQ response */
399 return xfer_deliver_iob_meta ( &tftp->socket, iobuf, &meta );
403 * Transmit next relevant packet
405 * @v tftp TFTP connection
406 * @ret rc Return status code
408 static int tftp_send_packet ( struct tftp_request *tftp ) {
410 /* Update retransmission timer */
411 stop_timer ( &tftp->timer );
412 start_timer ( &tftp->timer );
414 /* Send RRQ or ACK as appropriate */
415 if ( ! tftp->peer.st_family ) {
416 return tftp_send_rrq ( tftp );
418 if ( tftp->flags & TFTP_FL_SEND_ACK ) {
419 return tftp_send_ack ( tftp );
427 * Handle TFTP retransmission timer expiry
429 * @v timer Retry timer
430 * @v fail Failure indicator
432 static void tftp_timer_expired ( struct retry_timer *timer, int fail ) {
433 struct tftp_request *tftp =
434 container_of ( timer, struct tftp_request, timer );
437 /* If we are doing MTFTP, attempt the various recovery strategies */
438 if ( tftp->flags & TFTP_FL_MTFTP_RECOVERY ) {
439 if ( tftp->peer.st_family ) {
440 /* If we have received any response from the server,
441 * try resending the RRQ to restart the download.
443 DBGC ( tftp, "TFTP %p attempting reopen\n", tftp );
444 if ( ( rc = tftp_reopen ( tftp ) ) != 0 )
447 /* Fall back to plain TFTP after several attempts */
448 tftp->mtftp_timeouts++;
449 DBGC ( tftp, "TFTP %p timeout %d waiting for MTFTP "
450 "open\n", tftp, tftp->mtftp_timeouts );
452 if ( tftp->mtftp_timeouts > MTFTP_MAX_TIMEOUTS ) {
453 DBGC ( tftp, "TFTP %p falling back to plain "
455 tftp->flags = TFTP_FL_RRQ_SIZES;
457 /* Close multicast socket */
458 xfer_close ( &tftp->mc_socket, 0 );
460 /* Reset retry timer */
461 start_timer_nodelay ( &tftp->timer );
463 /* The blocksize may change: discard
466 bitmap_free ( &tftp->bitmap );
467 memset ( &tftp->bitmap, 0,
468 sizeof ( tftp->bitmap ) );
470 /* Reopen on standard TFTP port */
471 tftp->port = TFTP_PORT;
472 if ( ( rc = tftp_reopen ( tftp ) ) != 0 )
477 /* Not doing MTFTP (or have fallen back to plain
478 * TFTP); fail as per normal.
485 tftp_send_packet ( tftp );
489 tftp_done ( tftp, rc );
493 * Process TFTP "blksize" option
495 * @v tftp TFTP connection
496 * @v value Option value
497 * @ret rc Return status code
499 static int tftp_process_blksize ( struct tftp_request *tftp,
500 const char *value ) {
503 tftp->blksize = strtoul ( value, &end, 10 );
505 DBGC ( tftp, "TFTP %p got invalid blksize \"%s\"\n",
509 DBGC ( tftp, "TFTP %p blksize=%d\n", tftp, tftp->blksize );
515 * Process TFTP "tsize" option
517 * @v tftp TFTP connection
518 * @v value Option value
519 * @ret rc Return status code
521 static int tftp_process_tsize ( struct tftp_request *tftp,
522 const char *value ) {
525 tftp->tsize = strtoul ( value, &end, 10 );
527 DBGC ( tftp, "TFTP %p got invalid tsize \"%s\"\n",
531 DBGC ( tftp, "TFTP %p tsize=%ld\n", tftp, tftp->tsize );
537 * Process TFTP "multicast" option
539 * @v tftp TFTP connection
540 * @v value Option value
541 * @ret rc Return status code
543 static int tftp_process_multicast ( struct tftp_request *tftp,
544 const char *value ) {
547 struct sockaddr_in sin;
549 char buf[ strlen ( value ) + 1 ];
557 /* Split value into "addr,port,mc" fields */
558 memcpy ( buf, value, sizeof ( buf ) );
560 port = strchr ( addr, ',' );
562 DBGC ( tftp, "TFTP %p multicast missing port,mc\n", tftp );
566 mc = strchr ( port, ',' );
568 DBGC ( tftp, "TFTP %p multicast missing mc\n", tftp );
573 /* Parse parameters */
574 if ( strtoul ( mc, &mc_end, 0 ) == 0 )
575 tftp->flags &= ~TFTP_FL_SEND_ACK;
577 DBGC ( tftp, "TFTP %p multicast invalid mc %s\n", tftp, mc );
580 DBGC ( tftp, "TFTP %p is%s the master client\n",
581 tftp, ( ( tftp->flags & TFTP_FL_SEND_ACK ) ? "" : " not" ) );
582 if ( *addr && *port ) {
583 socket.sin.sin_family = AF_INET;
584 if ( inet_aton ( addr, &socket.sin.sin_addr ) == 0 ) {
585 DBGC ( tftp, "TFTP %p multicast invalid IP address "
586 "%s\n", tftp, addr );
589 DBGC ( tftp, "TFTP %p multicast IP address %s\n",
590 tftp, inet_ntoa ( socket.sin.sin_addr ) );
591 socket.sin.sin_port = htons ( strtoul ( port, &port_end, 0 ) );
593 DBGC ( tftp, "TFTP %p multicast invalid port %s\n",
597 DBGC ( tftp, "TFTP %p multicast port %d\n",
598 tftp, ntohs ( socket.sin.sin_port ) );
599 if ( ( rc = tftp_reopen_mc ( tftp, &socket.sa ) ) != 0 )
612 * @v tftp TFTP connection
613 * @v value Option value
614 * @ret rc Return status code
616 int ( * process ) ( struct tftp_request *tftp, const char *value );
619 /** Recognised TFTP options */
620 static struct tftp_option tftp_options[] = {
621 { "blksize", tftp_process_blksize },
622 { "tsize", tftp_process_tsize },
623 { "multicast", tftp_process_multicast },
628 * Process TFTP option
630 * @v tftp TFTP connection
631 * @v name Option name
632 * @v value Option value
633 * @ret rc Return status code
635 static int tftp_process_option ( struct tftp_request *tftp,
636 const char *name, const char *value ) {
637 struct tftp_option *option;
639 for ( option = tftp_options ; option->name ; option++ ) {
640 if ( strcasecmp ( name, option->name ) == 0 )
641 return option->process ( tftp, value );
644 DBGC ( tftp, "TFTP %p received unknown option \"%s\" = \"%s\"\n",
647 /* Unknown options should be silently ignored */
654 * @v tftp TFTP connection
655 * @v buf Temporary data buffer
656 * @v len Length of temporary data buffer
657 * @ret rc Return status code
659 static int tftp_rx_oack ( struct tftp_request *tftp, void *buf, size_t len ) {
660 struct tftp_oack *oack = buf;
661 char *end = buf + len;
667 if ( len < sizeof ( *oack ) ) {
668 DBGC ( tftp, "TFTP %p received underlength OACK packet "
669 "length %zd\n", tftp, len );
673 if ( end[-1] != '\0' ) {
674 DBGC ( tftp, "TFTP %p received OACK missing final NUL\n",
680 /* Process each option in turn */
682 while ( name < end ) {
683 value = ( name + strlen ( name ) + 1 );
684 if ( value == end ) {
685 DBGC ( tftp, "TFTP %p received OACK missing value "
686 "for option \"%s\"\n", tftp, name );
690 if ( ( rc = tftp_process_option ( tftp, name, value ) ) != 0 )
692 name = ( value + strlen ( value ) + 1 );
695 /* Process tsize information, if available */
697 if ( ( rc = tftp_presize ( tftp, tftp->tsize ) ) != 0 )
701 /* Request next data block */
702 tftp_send_packet ( tftp );
706 tftp_done ( tftp, rc );
713 * @v tftp TFTP connection
714 * @v iobuf I/O buffer
715 * @ret rc Return status code
717 * Takes ownership of I/O buffer.
719 static int tftp_rx_data ( struct tftp_request *tftp,
720 struct io_buffer *iobuf ) {
721 struct tftp_data *data = iobuf->data;
722 struct xfer_metadata meta;
729 if ( iob_len ( iobuf ) < sizeof ( *data ) ) {
730 DBGC ( tftp, "TFTP %p received underlength DATA packet "
731 "length %zd\n", tftp, iob_len ( iobuf ) );
737 block = ( ntohs ( data->block ) - 1 );
738 offset = ( block * tftp->blksize );
739 iob_pull ( iobuf, sizeof ( *data ) );
740 data_len = iob_len ( iobuf );
741 if ( data_len > tftp->blksize ) {
742 DBGC ( tftp, "TFTP %p received overlength DATA packet "
743 "length %zd\n", tftp, data_len );
749 memset ( &meta, 0, sizeof ( meta ) );
750 meta.whence = SEEK_SET;
751 meta.offset = offset;
752 rc = xfer_deliver_iob_meta ( &tftp->xfer, iobuf, &meta );
755 DBGC ( tftp, "TFTP %p could not deliver data: %s\n",
756 tftp, strerror ( rc ) );
760 /* Ensure block bitmap is ready */
761 if ( ( rc = tftp_presize ( tftp, ( offset + data_len ) ) ) != 0 )
764 /* Mark block as received */
765 bitmap_set ( &tftp->bitmap, block );
767 /* Acknowledge block */
768 tftp_send_packet ( tftp );
770 /* If all blocks have been received, finish. */
771 if ( bitmap_full ( &tftp->bitmap ) )
772 tftp_done ( tftp, 0 );
777 tftp_done ( tftp, rc );
781 /** Translation between TFTP errors and internal error numbers */
782 static const int tftp_errors[] = {
783 [TFTP_ERR_FILE_NOT_FOUND] = ENOENT,
784 [TFTP_ERR_ACCESS_DENIED] = EACCES,
785 [TFTP_ERR_ILLEGAL_OP] = ENOTSUP,
791 * @v tftp TFTP connection
792 * @v buf Temporary data buffer
793 * @v len Length of temporary data buffer
794 * @ret rc Return status code
796 static int tftp_rx_error ( struct tftp_request *tftp, void *buf, size_t len ) {
797 struct tftp_error *error = buf;
802 if ( len < sizeof ( *error ) ) {
803 DBGC ( tftp, "TFTP %p received underlength ERROR packet "
804 "length %zd\n", tftp, len );
808 DBGC ( tftp, "TFTP %p received ERROR packet with code %d, message "
809 "\"%s\"\n", tftp, ntohs ( error->errcode ), error->errmsg );
811 /* Determine final operation result */
812 err = ntohs ( error->errcode );
813 if ( err < ( sizeof ( tftp_errors ) / sizeof ( tftp_errors[0] ) ) )
814 rc = -tftp_errors[err];
818 /* Close TFTP request */
819 tftp_done ( tftp, rc );
827 * @v tftp TFTP connection
828 * @v iobuf I/O buffer
829 * @v meta Transfer metadata, or NULL
830 * @ret rc Return status code
832 static int tftp_rx ( struct tftp_request *tftp,
833 struct io_buffer *iobuf,
834 struct xfer_metadata *meta ) {
835 struct sockaddr_tcpip *st_src;
836 struct tftp_common *common = iobuf->data;
837 size_t len = iob_len ( iobuf );
841 if ( len < sizeof ( *common ) ) {
842 DBGC ( tftp, "TFTP %p received underlength packet length "
843 "%zd\n", tftp, len );
847 DBGC ( tftp, "TFTP %p received packet without metadata\n",
852 DBGC ( tftp, "TFTP %p received packet without source port\n",
857 /* Filter by TID. Set TID on first response received */
858 st_src = ( struct sockaddr_tcpip * ) meta->src;
859 if ( ! tftp->peer.st_family ) {
860 memcpy ( &tftp->peer, st_src, sizeof ( tftp->peer ) );
861 DBGC ( tftp, "TFTP %p using remote port %d\n", tftp,
862 ntohs ( tftp->peer.st_port ) );
863 } else if ( memcmp ( &tftp->peer, st_src,
864 sizeof ( tftp->peer ) ) != 0 ) {
865 DBGC ( tftp, "TFTP %p received packet from wrong source (got "
866 "%d, wanted %d)\n", tftp, ntohs ( st_src->st_port ),
867 ntohs ( tftp->peer.st_port ) );
871 switch ( common->opcode ) {
872 case htons ( TFTP_OACK ):
873 rc = tftp_rx_oack ( tftp, iobuf->data, len );
875 case htons ( TFTP_DATA ):
876 rc = tftp_rx_data ( tftp, iobuf );
879 case htons ( TFTP_ERROR ):
880 rc = tftp_rx_error ( tftp, iobuf->data, len );
883 DBGC ( tftp, "TFTP %p received strange packet type %d\n",
884 tftp, ntohs ( common->opcode ) );
894 * Receive new data via socket
896 * @v socket Transport layer interface
897 * @v iobuf I/O buffer
898 * @v meta Transfer metadata, or NULL
899 * @ret rc Return status code
901 static int tftp_socket_deliver_iob ( struct xfer_interface *socket,
902 struct io_buffer *iobuf,
903 struct xfer_metadata *meta ) {
904 struct tftp_request *tftp =
905 container_of ( socket, struct tftp_request, socket );
907 /* Enable sending ACKs when we receive a unicast packet. This
908 * covers three cases:
910 * 1. Standard TFTP; we should always send ACKs, and will
911 * always receive a unicast packet before we need to send the
914 * 2. RFC2090 multicast TFTP; the only unicast packets we will
915 * receive are the OACKs; enable sending ACKs here (before
916 * processing the OACK) and disable it when processing the
917 * multicast option if we are not the master client.
919 * 3. MTFTP; receiving a unicast datagram indicates that we
920 * are the "master client" and should send ACKs.
922 tftp->flags |= TFTP_FL_SEND_ACK;
924 return tftp_rx ( tftp, iobuf, meta );
927 /** TFTP socket operations */
928 static struct xfer_interface_operations tftp_socket_operations = {
929 .close = ignore_xfer_close,
930 .vredirect = xfer_vopen,
931 .window = unlimited_xfer_window,
932 .alloc_iob = default_xfer_alloc_iob,
933 .deliver_iob = tftp_socket_deliver_iob,
934 .deliver_raw = xfer_deliver_as_iob,
938 * Receive new data via multicast socket
940 * @v mc_socket Multicast transport layer interface
941 * @v iobuf I/O buffer
942 * @v meta Transfer metadata, or NULL
943 * @ret rc Return status code
945 static int tftp_mc_socket_deliver_iob ( struct xfer_interface *mc_socket,
946 struct io_buffer *iobuf,
947 struct xfer_metadata *meta ) {
948 struct tftp_request *tftp =
949 container_of ( mc_socket, struct tftp_request, mc_socket );
951 return tftp_rx ( tftp, iobuf, meta );
954 /** TFTP multicast socket operations */
955 static struct xfer_interface_operations tftp_mc_socket_operations = {
956 .close = ignore_xfer_close,
957 .vredirect = xfer_vopen,
958 .window = unlimited_xfer_window,
959 .alloc_iob = default_xfer_alloc_iob,
960 .deliver_iob = tftp_mc_socket_deliver_iob,
961 .deliver_raw = xfer_deliver_as_iob,
965 * Close TFTP data transfer interface
967 * @v xfer Data transfer interface
968 * @v rc Reason for close
970 static void tftp_xfer_close ( struct xfer_interface *xfer, int rc ) {
971 struct tftp_request *tftp =
972 container_of ( xfer, struct tftp_request, xfer );
974 DBGC ( tftp, "TFTP %p interface closed: %s\n",
975 tftp, strerror ( rc ) );
977 tftp_done ( tftp, rc );
980 /** TFTP data transfer interface operations */
981 static struct xfer_interface_operations tftp_xfer_operations = {
982 .close = tftp_xfer_close,
983 .vredirect = ignore_xfer_vredirect,
984 .window = unlimited_xfer_window,
985 .alloc_iob = default_xfer_alloc_iob,
986 .deliver_iob = xfer_deliver_as_raw,
987 .deliver_raw = ignore_xfer_deliver_raw,
991 * Initiate TFTP/TFTM/MTFTP download
993 * @v xfer Data transfer interface
994 * @v uri Uniform Resource Identifier
995 * @ret rc Return status code
997 static int tftp_core_open ( struct xfer_interface *xfer, struct uri *uri,
998 unsigned int default_port,
999 struct sockaddr *multicast,
1000 unsigned int flags ) {
1001 struct tftp_request *tftp;
1010 /* Allocate and populate TFTP structure */
1011 tftp = zalloc ( sizeof ( *tftp ) );
1014 tftp->refcnt.free = tftp_free;
1015 xfer_init ( &tftp->xfer, &tftp_xfer_operations, &tftp->refcnt );
1016 tftp->uri = uri_get ( uri );
1017 xfer_init ( &tftp->socket, &tftp_socket_operations, &tftp->refcnt );
1018 xfer_init ( &tftp->mc_socket, &tftp_mc_socket_operations,
1020 tftp->blksize = TFTP_DEFAULT_BLKSIZE;
1021 tftp->flags = flags;
1022 tftp->timer.expired = tftp_timer_expired;
1025 tftp->port = uri_port ( tftp->uri, default_port );
1026 if ( ( rc = tftp_reopen ( tftp ) ) != 0 )
1029 /* Open multicast socket */
1031 if ( ( rc = tftp_reopen_mc ( tftp, multicast ) ) != 0 )
1035 /* Start timer to initiate RRQ */
1036 start_timer_nodelay ( &tftp->timer );
1038 /* Attach to parent interface, mortalise self, and return */
1039 xfer_plug_plug ( &tftp->xfer, xfer );
1040 ref_put ( &tftp->refcnt );
1044 DBGC ( tftp, "TFTP %p could not create request: %s\n",
1045 tftp, strerror ( rc ) );
1046 tftp_done ( tftp, rc );
1047 ref_put ( &tftp->refcnt );
1052 * Initiate TFTP download
1054 * @v xfer Data transfer interface
1055 * @v uri Uniform Resource Identifier
1056 * @ret rc Return status code
1058 static int tftp_open ( struct xfer_interface *xfer, struct uri *uri ) {
1059 return tftp_core_open ( xfer, uri, TFTP_PORT, NULL,
1060 TFTP_FL_RRQ_SIZES );
1064 /** TFTP URI opener */
1065 struct uri_opener tftp_uri_opener __uri_opener = {
1071 * Initiate TFTM download
1073 * @v xfer Data transfer interface
1074 * @v uri Uniform Resource Identifier
1075 * @ret rc Return status code
1077 static int tftm_open ( struct xfer_interface *xfer, struct uri *uri ) {
1078 return tftp_core_open ( xfer, uri, TFTP_PORT, NULL,
1079 ( TFTP_FL_RRQ_SIZES |
1080 TFTP_FL_RRQ_MULTICAST ) );
1084 /** TFTM URI opener */
1085 struct uri_opener tftm_uri_opener __uri_opener = {
1091 * Initiate MTFTP download
1093 * @v xfer Data transfer interface
1094 * @v uri Uniform Resource Identifier
1095 * @ret rc Return status code
1097 static int mtftp_open ( struct xfer_interface *xfer, struct uri *uri ) {
1098 return tftp_core_open ( xfer, uri, MTFTP_PORT,
1099 ( struct sockaddr * ) &tftp_mtftp_socket,
1100 TFTP_FL_MTFTP_RECOVERY );
1103 /** MTFTP URI opener */
1104 struct uri_opener mtftp_uri_opener __uri_opener = {
1109 /******************************************************************************
1113 ******************************************************************************
1116 /** TFTP server setting */
1117 struct setting next_server_setting __setting = {
1118 .name = "next-server",
1119 .description = "TFTP server",
1120 .tag = DHCP_EB_SIADDR,
1121 .type = &setting_type_ipv4,
1125 * Apply TFTP configuration settings
1127 * @ret rc Return status code
1129 static int tftp_apply_settings ( void ) {
1130 static struct in_addr tftp_server = { 0 };
1131 struct in_addr last_tftp_server;
1132 char uri_string[32];
1135 /* Retrieve TFTP server setting */
1136 last_tftp_server = tftp_server;
1137 fetch_ipv4_setting ( NULL, &next_server_setting, &tftp_server );
1139 /* If TFTP server setting has changed, set the current working
1140 * URI to match. Do it only when the TFTP server has changed
1141 * to try to minimise surprises to the user, who probably
1142 * won't expect the CWURI to change just because they updated
1143 * an unrelated setting and triggered all the settings
1146 if ( tftp_server.s_addr != last_tftp_server.s_addr ) {
1147 snprintf ( uri_string, sizeof ( uri_string ),
1148 "tftp://%s/", inet_ntoa ( tftp_server ) );
1149 uri = parse_uri ( uri_string );
1159 /** TFTP settings applicator */
1160 struct settings_applicator tftp_settings_applicator __settings_applicator = {
1161 .apply = tftp_apply_settings,