tftp.c File Reference

TFTP protocol. More...

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <byteswap.h>
#include <errno.h>
#include <assert.h>
#include <gpxe/refcnt.h>
#include <gpxe/xfer.h>
#include <gpxe/open.h>
#include <gpxe/uri.h>
#include <gpxe/tcpip.h>
#include <gpxe/retry.h>
#include <gpxe/features.h>
#include <gpxe/bitmap.h>
#include <gpxe/settings.h>
#include <gpxe/dhcp.h>
#include <gpxe/tftp.h>

Go to the source code of this file.

Data Structures

struct  tftp_request
 A TFTP request. More...
struct  tftp_option
 A TFTP option. More...

Defines

#define ETFTP_INVALID_BLKSIZE   EUNIQ_01
#define ETFTP_INVALID_TSIZE   EUNIQ_02
#define ETFTP_MC_NO_PORT   EUNIQ_03
#define ETFTP_MC_NO_MC   EUNIQ_04
#define ETFTP_MC_INVALID_MC   EUNIQ_05
#define ETFTP_MC_INVALID_IP   EUNIQ_06
#define ETFTP_MC_INVALID_PORT   EUNIQ_07
#define MTFTP_MAX_TIMEOUTS   3
 Maximum number of MTFTP open requests before falling back to TFTP.

Enumerations

enum  {
  TFTP_FL_SEND_ACK = 0x0001, TFTP_FL_RRQ_SIZES = 0x0002, TFTP_FL_RRQ_MULTICAST = 0x0004, TFTP_FL_MTFTP_RECOVERY = 0x0008,
  TFTP_FL_SIZEONLY = 0x0010
}
 TFTP request flags. More...

Functions

 FILE_LICENCE (GPL2_OR_LATER)
 FEATURE (FEATURE_PROTOCOL,"TFTP", DHCP_EB_FEATURE_TFTP, 1)
static void tftp_free (struct refcnt *refcnt)
 Free TFTP request.
static void tftp_done (struct tftp_request *tftp, int rc)
 Mark TFTP request as complete.
static int tftp_reopen (struct tftp_request *tftp)
 Reopen TFTP socket.
static int tftp_reopen_mc (struct tftp_request *tftp, struct sockaddr *local)
 Reopen TFTP multicast socket.
static int tftp_presize (struct tftp_request *tftp, size_t filesize)
 Presize TFTP receive buffers and block bitmap.
void tftp_set_request_blksize (unsigned int blksize)
 Set TFTP request blocksize.
void tftp_set_mtftp_address (struct in_addr address)
 Set MTFTP multicast address.
void tftp_set_mtftp_port (unsigned int port)
 Set MTFTP multicast port.
static int tftp_send_rrq (struct tftp_request *tftp)
 Transmit RRQ.
static int tftp_send_ack (struct tftp_request *tftp)
 Transmit ACK.
static int tftp_send_error (struct tftp_request *tftp, int errcode, const char *errmsg)
 Transmit ERROR (Abort).
static int tftp_send_packet (struct tftp_request *tftp)
 Transmit next relevant packet.
static void tftp_timer_expired (struct retry_timer *timer, int fail)
 Handle TFTP retransmission timer expiry.
static int tftp_process_blksize (struct tftp_request *tftp, const char *value)
 Process TFTP "blksize" option.
static int tftp_process_tsize (struct tftp_request *tftp, const char *value)
 Process TFTP "tsize" option.
static int tftp_process_multicast (struct tftp_request *tftp, const char *value)
 Process TFTP "multicast" option.
static int tftp_process_option (struct tftp_request *tftp, const char *name, const char *value)
 Process TFTP option.
static int tftp_rx_oack (struct tftp_request *tftp, void *buf, size_t len)
 Receive OACK.
static int tftp_rx_data (struct tftp_request *tftp, struct io_buffer *iobuf)
 Receive DATA.
static int tftp_rx_error (struct tftp_request *tftp, void *buf, size_t len)
 Receive ERROR.
static int tftp_rx (struct tftp_request *tftp, struct io_buffer *iobuf, struct xfer_metadata *meta)
 Receive new data.
static int tftp_socket_deliver_iob (struct xfer_interface *socket, struct io_buffer *iobuf, struct xfer_metadata *meta)
 Receive new data via socket.
static int tftp_mc_socket_deliver_iob (struct xfer_interface *mc_socket, struct io_buffer *iobuf, struct xfer_metadata *meta)
 Receive new data via multicast socket.
static void tftp_xfer_close (struct xfer_interface *xfer, int rc)
 Close TFTP data transfer interface.
static size_t tftp_xfer_window (struct xfer_interface *xfer)
 Check flow control window.
static int tftp_core_open (struct xfer_interface *xfer, struct uri *uri, unsigned int default_port, struct sockaddr *multicast, unsigned int flags)
 Initiate TFTP/TFTM/MTFTP download.
static int tftp_open (struct xfer_interface *xfer, struct uri *uri)
 Initiate TFTP download.
static int tftpsize_open (struct xfer_interface *xfer, struct uri *uri)
 Initiate TFTP-size request.
static int tftm_open (struct xfer_interface *xfer, struct uri *uri)
 Initiate TFTM download.
static int mtftp_open (struct xfer_interface *xfer, struct uri *uri)
 Initiate MTFTP download.
static int tftp_apply_settings (void)
 Apply TFTP configuration settings.

Variables

static unsigned int tftp_request_blksize = TFTP_MAX_BLKSIZE
 TFTP requested blocksize.
static struct sockaddr_in tftp_mtftp_socket
 MTFTP multicast receive address.
static struct tftp_option tftp_options []
 Recognised TFTP options.
static const int tftp_errors []
 Translation between TFTP errors and internal error numbers.
static struct
xfer_interface_operations 
tftp_socket_operations
 TFTP socket operations.
static struct
xfer_interface_operations 
tftp_mc_socket_operations
 TFTP multicast socket operations.
static struct
xfer_interface_operations 
tftp_xfer_operations
 TFTP data transfer interface operations.
struct uri_opener tftp_uri_opener __uri_opener
 TFTP URI opener.
struct setting next_server_setting __setting
 TFTP server setting.
struct settings_applicator
tftp_settings_applicator 
__settings_applicator
 TFTP settings applicator.


Detailed Description

TFTP protocol.

Definition in file tftp.c.


Define Documentation

#define ETFTP_INVALID_BLKSIZE   EUNIQ_01

Definition at line 51 of file tftp.c.

Referenced by tftp_process_blksize().

#define ETFTP_INVALID_TSIZE   EUNIQ_02

Definition at line 52 of file tftp.c.

Referenced by tftp_process_tsize().

#define ETFTP_MC_NO_PORT   EUNIQ_03

Definition at line 53 of file tftp.c.

Referenced by tftp_process_multicast().

#define ETFTP_MC_NO_MC   EUNIQ_04

Definition at line 54 of file tftp.c.

Referenced by tftp_process_multicast().

#define ETFTP_MC_INVALID_MC   EUNIQ_05

Definition at line 55 of file tftp.c.

Referenced by tftp_process_multicast().

#define ETFTP_MC_INVALID_IP   EUNIQ_06

Definition at line 56 of file tftp.c.

Referenced by tftp_process_multicast().

#define ETFTP_MC_INVALID_PORT   EUNIQ_07

Definition at line 57 of file tftp.c.

Referenced by tftp_process_multicast().

#define MTFTP_MAX_TIMEOUTS   3

Maximum number of MTFTP open requests before falling back to TFTP.

Definition at line 141 of file tftp.c.

Referenced by tftp_timer_expired().


Enumeration Type Documentation

anonymous enum

TFTP request flags.

Enumerator:
TFTP_FL_SEND_ACK  Send ACK packets.
TFTP_FL_RRQ_SIZES  Request blksize and tsize options.
TFTP_FL_RRQ_MULTICAST  Request multicast option.
TFTP_FL_MTFTP_RECOVERY  Perform MTFTP recovery on timeout.
TFTP_FL_SIZEONLY  Only get filesize and then abort the transfer.

Definition at line 127 of file tftp.c.

00127      {
00128         /** Send ACK packets */
00129         TFTP_FL_SEND_ACK = 0x0001,
00130         /** Request blksize and tsize options */
00131         TFTP_FL_RRQ_SIZES = 0x0002,
00132         /** Request multicast option */
00133         TFTP_FL_RRQ_MULTICAST = 0x0004,
00134         /** Perform MTFTP recovery on timeout */
00135         TFTP_FL_MTFTP_RECOVERY = 0x0008,
00136         /** Only get filesize and then abort the transfer */
00137         TFTP_FL_SIZEONLY = 0x0010,
00138 };


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER   ) 

FEATURE ( FEATURE_PROTOCOL  ,
"TFTP"  ,
DHCP_EB_FEATURE_TFTP  ,
 
)

static void tftp_free ( struct refcnt refcnt  )  [static]

Free TFTP request.

Parameters:
refcnt Reference counter

Definition at line 148 of file tftp.c.

References tftp_request::bitmap, bitmap_free(), container_of, free(), and tftp_request::uri.

Referenced by tftp_core_open().

00148                                                 {
00149         struct tftp_request *tftp =
00150                 container_of ( refcnt, struct tftp_request, refcnt );
00151 
00152         uri_put ( tftp->uri );
00153         bitmap_free ( &tftp->bitmap );
00154         free ( tftp );
00155 }

static void tftp_done ( struct tftp_request tftp,
int  rc 
) [static]

Mark TFTP request as complete.

Parameters:
tftp TFTP connection
rc Return status code

Definition at line 163 of file tftp.c.

References DBGC, tftp_request::mc_socket, tftp_request::socket, stop_timer(), strerror(), tftp_request::timer, tftp_request::xfer, and xfer_close().

Referenced by tftp_core_open(), tftp_rx_data(), tftp_rx_error(), tftp_rx_oack(), tftp_timer_expired(), and tftp_xfer_close().

00163                                                             {
00164 
00165         DBGC ( tftp, "TFTP %p finished with status %d (%s)\n",
00166                tftp, rc, strerror ( rc ) );
00167 
00168         /* Stop the retry timer */
00169         stop_timer ( &tftp->timer );
00170 
00171         /* Close all data transfer interfaces */
00172         xfer_nullify ( &tftp->socket );
00173         xfer_close ( &tftp->socket, rc );
00174         xfer_nullify ( &tftp->mc_socket );
00175         xfer_close ( &tftp->mc_socket, rc );
00176         xfer_nullify ( &tftp->xfer );
00177         xfer_close ( &tftp->xfer, rc );
00178 }

static int tftp_reopen ( struct tftp_request tftp  )  [static]

Reopen TFTP socket.

Parameters:
tftp TFTP connection
Return values:
rc Return status code

Definition at line 186 of file tftp.c.

References DBGC, tftp_request::flags, uri::host, htons, memset(), NULL, tftp_request::peer, tftp_request::port, SOCK_DGRAM, tftp_request::socket, sockaddr_tcpip::st_port, strerror(), TFTP_FL_SEND_ACK, tftp_request::uri, xfer_close(), and xfer_open_named_socket().

Referenced by tftp_core_open(), and tftp_timer_expired().

00186                                                      {
00187         struct sockaddr_tcpip server;
00188         int rc;
00189 
00190         /* Close socket */
00191         xfer_close ( &tftp->socket, 0 );
00192 
00193         /* Disable ACK sending. */
00194         tftp->flags &= ~TFTP_FL_SEND_ACK;
00195 
00196         /* Reset peer address */
00197         memset ( &tftp->peer, 0, sizeof ( tftp->peer ) );
00198 
00199         /* Open socket */
00200         memset ( &server, 0, sizeof ( server ) );
00201         server.st_port = htons ( tftp->port );
00202         if ( ( rc = xfer_open_named_socket ( &tftp->socket, SOCK_DGRAM,
00203                                              ( struct sockaddr * ) &server,
00204                                              tftp->uri->host, NULL ) ) != 0 ) {
00205                 DBGC ( tftp, "TFTP %p could not open socket: %s\n",
00206                        tftp, strerror ( rc ) );
00207                 return rc;
00208         }
00209 
00210         return 0;
00211 }

static int tftp_reopen_mc ( struct tftp_request tftp,
struct sockaddr local 
) [static]

Reopen TFTP multicast socket.

Parameters:
tftp TFTP connection
local Local socket address
Return values:
rc Return status code

Definition at line 220 of file tftp.c.

References DBGC, tftp_request::mc_socket, SOCK_DGRAM, strerror(), xfer_close(), and xfer_open_socket().

Referenced by tftp_core_open(), and tftp_process_multicast().

00221                                                      {
00222         int rc;
00223 
00224         /* Close multicast socket */
00225         xfer_close ( &tftp->mc_socket, 0 );
00226 
00227         /* Open multicast socket.  We never send via this socket, so
00228          * use the local address as the peer address (since the peer
00229          * address cannot be NULL).
00230          */
00231         if ( ( rc = xfer_open_socket ( &tftp->mc_socket, SOCK_DGRAM,
00232                                        local, local ) ) != 0 ) {
00233                 DBGC ( tftp, "TFTP %p could not open multicast "
00234                        "socket: %s\n", tftp, strerror ( rc ) );
00235                 return rc;
00236         }
00237 
00238         return 0;
00239 }

static int tftp_presize ( struct tftp_request tftp,
size_t  filesize 
) [static]

Presize TFTP receive buffers and block bitmap.

Parameters:
tftp TFTP connection
filesize Known minimum file size
Return values:
rc Return status code

Definition at line 248 of file tftp.c.

References tftp_request::bitmap, bitmap_resize(), tftp_request::blksize, DBGC, tftp_request::filesize, SEEK_SET, strerror(), tftp_request::xfer, and xfer_seek().

Referenced by tftp_rx_data(), and tftp_rx_oack().

00248                                                                        {
00249         unsigned int num_blocks;
00250         int rc;
00251 
00252         /* Do nothing if we are already large enough */
00253         if ( filesize <= tftp->filesize )
00254                 return 0;
00255 
00256         /* Record filesize */
00257         tftp->filesize = filesize;
00258 
00259         /* Notify recipient of file size */
00260         xfer_seek ( &tftp->xfer, filesize, SEEK_SET );
00261         xfer_seek ( &tftp->xfer, 0, SEEK_SET );
00262 
00263         /* Calculate expected number of blocks.  Note that files whose
00264          * length is an exact multiple of the blocksize will have a
00265          * trailing zero-length block, which must be included.
00266          */
00267         num_blocks = ( ( filesize / tftp->blksize ) + 1 );
00268         if ( ( rc = bitmap_resize ( &tftp->bitmap, num_blocks ) ) != 0 ) {
00269                 DBGC ( tftp, "TFTP %p could not resize bitmap to %d blocks: "
00270                        "%s\n", tftp, num_blocks, strerror ( rc ) );
00271                 return rc;
00272         }
00273 
00274         return 0;
00275 }

void tftp_set_request_blksize ( unsigned int  blksize  ) 

Set TFTP request blocksize.

Parameters:
blksize Requested block size

Definition at line 289 of file tftp.c.

References TFTP_DEFAULT_BLKSIZE, and tftp_request_blksize.

00289                                                        {
00290         if ( blksize < TFTP_DEFAULT_BLKSIZE )
00291                 blksize = TFTP_DEFAULT_BLKSIZE;
00292         tftp_request_blksize = blksize;
00293 }

void tftp_set_mtftp_address ( struct in_addr  address  ) 

Set MTFTP multicast address.

Parameters:
address Multicast IPv4 address

Definition at line 311 of file tftp.c.

References sockaddr_in::sin_addr.

00311                                                        {
00312         tftp_mtftp_socket.sin_addr = address;
00313 }

void tftp_set_mtftp_port ( unsigned int  port  ) 

Set MTFTP multicast port.

Parameters:
port Multicast port

Definition at line 320 of file tftp.c.

References htons, and sockaddr_in::sin_port.

00320                                                {
00321         tftp_mtftp_socket.sin_port = htons ( port );
00322 }

static int tftp_send_rrq ( struct tftp_request tftp  )  [static]

Transmit RRQ.

Parameters:
tftp TFTP connection
Return values:
rc Return status code

Definition at line 330 of file tftp.c.

References DBGC, ENOMEM, tftp_request::flags, htons, iob_put, iob_tailroom(), tftp_rrq::opcode, uri::path, snprintf(), tftp_request::socket, strlen(), io_buffer::tail, TFTP_FL_RRQ_MULTICAST, TFTP_FL_RRQ_SIZES, tftp_request_blksize, TFTP_RRQ, tftp_request::uri, xfer_alloc_iob(), and xfer_deliver_iob().

Referenced by tftp_send_packet().

00330                                                        {
00331         struct tftp_rrq *rrq;
00332         const char *path;
00333         size_t len;
00334         struct io_buffer *iobuf;
00335 
00336         /* Strip initial '/' if present.  If we were opened via the
00337          * URI interface, then there will be an initial '/', since a
00338          * full tftp:// URI provides no way to specify a non-absolute
00339          * path.  However, many TFTP servers (particularly Windows
00340          * TFTP servers) complain about having an initial '/', and it
00341          * violates user expectations to have a '/' silently added to
00342          * the DHCP-specified filename.
00343          */
00344         path = tftp->uri->path;
00345         if ( *path == '/' )
00346                 path++;
00347 
00348         DBGC ( tftp, "TFTP %p requesting \"%s\"\n", tftp, path );
00349 
00350         /* Allocate buffer */
00351         len = ( sizeof ( *rrq ) + strlen ( path ) + 1 /* NUL */
00352                 + 5 + 1 /* "octet" + NUL */
00353                 + 7 + 1 + 5 + 1 /* "blksize" + NUL + ddddd + NUL */
00354                 + 5 + 1 + 1 + 1 /* "tsize" + NUL + "0" + NUL */ 
00355                 + 9 + 1 + 1 /* "multicast" + NUL + NUL */ );
00356         iobuf = xfer_alloc_iob ( &tftp->socket, len );
00357         if ( ! iobuf )
00358                 return -ENOMEM;
00359 
00360         /* Build request */
00361         rrq = iob_put ( iobuf, sizeof ( *rrq ) );
00362         rrq->opcode = htons ( TFTP_RRQ );
00363         iob_put ( iobuf, snprintf ( iobuf->tail, iob_tailroom ( iobuf ),
00364                                     "%s%coctet", path, 0 ) + 1 );
00365         if ( tftp->flags & TFTP_FL_RRQ_SIZES ) {
00366                 iob_put ( iobuf, snprintf ( iobuf->tail,
00367                                             iob_tailroom ( iobuf ),
00368                                             "blksize%c%d%ctsize%c0", 0,
00369                                             tftp_request_blksize, 0, 0 ) + 1 );
00370         }
00371         if ( tftp->flags & TFTP_FL_RRQ_MULTICAST ) {
00372                 iob_put ( iobuf, snprintf ( iobuf->tail,
00373                                             iob_tailroom ( iobuf ),
00374                                             "multicast%c", 0 ) + 1 );
00375         }
00376 
00377         /* RRQ always goes to the address specified in the initial
00378          * xfer_open() call
00379          */
00380         return xfer_deliver_iob ( &tftp->socket, iobuf );
00381 }

static int tftp_send_ack ( struct tftp_request tftp  )  [static]

Transmit ACK.

Parameters:
tftp TFTP connection
Return values:
rc Return status code

Definition at line 389 of file tftp.c.

References tftp_request::bitmap, bitmap_first_gap(), tftp_ack::block, DBGC2, xfer_metadata::dest, ENOMEM, htons, iob_put, tftp_ack::opcode, tftp_request::peer, tftp_request::socket, TFTP_ACK, xfer_alloc_iob(), and xfer_deliver_iob_meta().

Referenced by tftp_send_packet().

00389                                                        {
00390         struct tftp_ack *ack;
00391         struct io_buffer *iobuf;
00392         struct xfer_metadata meta = {
00393                 .dest = ( struct sockaddr * ) &tftp->peer,
00394         };
00395         unsigned int block;
00396 
00397         /* Determine next required block number */
00398         block = bitmap_first_gap ( &tftp->bitmap );
00399         DBGC2 ( tftp, "TFTP %p sending ACK for block %d\n", tftp, block );
00400 
00401         /* Allocate buffer */
00402         iobuf = xfer_alloc_iob ( &tftp->socket, sizeof ( *ack ) );
00403         if ( ! iobuf )
00404                 return -ENOMEM;
00405 
00406         /* Build ACK */
00407         ack = iob_put ( iobuf, sizeof ( *ack ) );
00408         ack->opcode = htons ( TFTP_ACK );
00409         ack->block = htons ( block );
00410 
00411         /* ACK always goes to the peer recorded from the RRQ response */
00412         return xfer_deliver_iob_meta ( &tftp->socket, iobuf, &meta );
00413 }

static int tftp_send_error ( struct tftp_request tftp,
int  errcode,
const char *  errmsg 
) [static]

Transmit ERROR (Abort).

Parameters:
tftp TFTP connection
errcode TFTP error code
errmsg Error message string
Return values:
rc Return status code

Definition at line 423 of file tftp.c.

References DBGC2, xfer_metadata::dest, ENOMEM, tftp_error::errcode, tftp_error::errmsg, htons, iob_put, tftp_error::opcode, tftp_request::peer, tftp_request::socket, strcpy(), strlen(), TFTP_ERROR, xfer_alloc_iob(), and xfer_deliver_iob_meta().

Referenced by tftp_rx_data(), and tftp_rx_oack().

00424                                                   {
00425         struct tftp_error *err;
00426         struct io_buffer *iobuf;
00427         struct xfer_metadata meta = {
00428                 .dest = ( struct sockaddr * ) &tftp->peer,
00429         };
00430         size_t msglen;
00431 
00432         DBGC2 ( tftp, "TFTP %p sending ERROR %d: %s\n", tftp, errcode,
00433                 errmsg );
00434 
00435         /* Allocate buffer */
00436         msglen = sizeof ( *err ) + strlen ( errmsg ) + 1 /* NUL */;
00437         iobuf = xfer_alloc_iob ( &tftp->socket, msglen );
00438         if ( ! iobuf )
00439                 return -ENOMEM;
00440 
00441         /* Build ERROR */
00442         err = iob_put ( iobuf, msglen );
00443         err->opcode = htons ( TFTP_ERROR );
00444         err->errcode = htons ( errcode );
00445         strcpy ( err->errmsg, errmsg );
00446 
00447         /* ERR always goes to the peer recorded from the RRQ response */
00448         return xfer_deliver_iob_meta ( &tftp->socket, iobuf, &meta );
00449 }

static int tftp_send_packet ( struct tftp_request tftp  )  [static]

Transmit next relevant packet.

Parameters:
tftp TFTP connection
Return values:
rc Return status code

Definition at line 457 of file tftp.c.

References tftp_request::flags, tftp_request::peer, tftp_request::socket, sockaddr_tcpip::st_family, start_timer(), start_timer_nodelay(), stop_timer(), TFTP_FL_SEND_ACK, tftp_send_ack(), tftp_send_rrq(), tftp_request::timer, and xfer_window().

Referenced by tftp_rx_data(), tftp_rx_oack(), and tftp_timer_expired().

00457                                                           {
00458 
00459         /* Update retransmission timer.  While name resolution takes place the
00460          * window is zero.  Avoid unnecessary delay after name resolution
00461          * completes by retrying immediately.
00462          */
00463         stop_timer ( &tftp->timer );
00464         if ( xfer_window ( &tftp->socket ) ) {
00465                 start_timer ( &tftp->timer );
00466         } else {
00467                 start_timer_nodelay ( &tftp->timer );
00468         }
00469 
00470         /* Send RRQ or ACK as appropriate */
00471         if ( ! tftp->peer.st_family ) {
00472                 return tftp_send_rrq ( tftp );
00473         } else {
00474                 if ( tftp->flags & TFTP_FL_SEND_ACK ) {
00475                         return tftp_send_ack ( tftp );
00476                 } else {
00477                         return 0;
00478                 }
00479         }
00480 }

static void tftp_timer_expired ( struct retry_timer timer,
int  fail 
) [static]

Handle TFTP retransmission timer expiry.

Parameters:
timer Retry timer
fail Failure indicator

Definition at line 488 of file tftp.c.

References tftp_request::bitmap, bitmap_free(), container_of, DBGC, ETIMEDOUT, tftp_request::flags, tftp_request::mc_socket, memset(), MTFTP_MAX_TIMEOUTS, tftp_request::mtftp_timeouts, tftp_request::peer, tftp_request::port, sockaddr_tcpip::st_family, start_timer_nodelay(), tftp_done(), TFTP_FL_MTFTP_RECOVERY, TFTP_FL_RRQ_SIZES, TFTP_PORT, tftp_reopen(), tftp_send_packet(), tftp_request::timer, and xfer_close().

Referenced by tftp_core_open().

00488                                                                        {
00489         struct tftp_request *tftp =
00490                 container_of ( timer, struct tftp_request, timer );
00491         int rc;
00492 
00493         /* If we are doing MTFTP, attempt the various recovery strategies */
00494         if ( tftp->flags & TFTP_FL_MTFTP_RECOVERY ) {
00495                 if ( tftp->peer.st_family ) {
00496                         /* If we have received any response from the server,
00497                          * try resending the RRQ to restart the download.
00498                          */
00499                         DBGC ( tftp, "TFTP %p attempting reopen\n", tftp );
00500                         if ( ( rc = tftp_reopen ( tftp ) ) != 0 )
00501                                 goto err;
00502                 } else {
00503                         /* Fall back to plain TFTP after several attempts */
00504                         tftp->mtftp_timeouts++;
00505                         DBGC ( tftp, "TFTP %p timeout %d waiting for MTFTP "
00506                                "open\n", tftp, tftp->mtftp_timeouts );
00507 
00508                         if ( tftp->mtftp_timeouts > MTFTP_MAX_TIMEOUTS ) {
00509                                 DBGC ( tftp, "TFTP %p falling back to plain "
00510                                        "TFTP\n", tftp );
00511                                 tftp->flags = TFTP_FL_RRQ_SIZES;
00512 
00513                                 /* Close multicast socket */
00514                                 xfer_close ( &tftp->mc_socket, 0 );
00515 
00516                                 /* Reset retry timer */
00517                                 start_timer_nodelay ( &tftp->timer );
00518 
00519                                 /* The blocksize may change: discard
00520                                  * the block bitmap
00521                                  */
00522                                 bitmap_free ( &tftp->bitmap );
00523                                 memset ( &tftp->bitmap, 0,
00524                                          sizeof ( tftp->bitmap ) );
00525 
00526                                 /* Reopen on standard TFTP port */
00527                                 tftp->port = TFTP_PORT;
00528                                 if ( ( rc = tftp_reopen ( tftp ) ) != 0 )
00529                                         goto err;
00530                         }
00531                 }
00532         } else {
00533                 /* Not doing MTFTP (or have fallen back to plain
00534                  * TFTP); fail as per normal.
00535                  */
00536                 if ( fail ) {
00537                         rc = -ETIMEDOUT;
00538                         goto err;
00539                 }
00540         }
00541         tftp_send_packet ( tftp );
00542         return;
00543 
00544  err:
00545         tftp_done ( tftp, rc );
00546 }

static int tftp_process_blksize ( struct tftp_request tftp,
const char *  value 
) [static]

Process TFTP "blksize" option.

Parameters:
tftp TFTP connection
value Option value
Return values:
rc Return status code

Definition at line 555 of file tftp.c.

References tftp_request::blksize, DBGC, EINVAL, ETFTP_INVALID_BLKSIZE, and strtoul().

00556                                                       {
00557         char *end;
00558 
00559         tftp->blksize = strtoul ( value, &end, 10 );
00560         if ( *end ) {
00561                 DBGC ( tftp, "TFTP %p got invalid blksize \"%s\"\n",
00562                        tftp, value );
00563                 return -( EINVAL | ETFTP_INVALID_BLKSIZE );
00564         }
00565         DBGC ( tftp, "TFTP %p blksize=%d\n", tftp, tftp->blksize );
00566 
00567         return 0;
00568 }

static int tftp_process_tsize ( struct tftp_request tftp,
const char *  value 
) [static]

Process TFTP "tsize" option.

Parameters:
tftp TFTP connection
value Option value
Return values:
rc Return status code

Definition at line 577 of file tftp.c.

References DBGC, EINVAL, ETFTP_INVALID_TSIZE, strtoul(), and tftp_request::tsize.

00578                                                     {
00579         char *end;
00580 
00581         tftp->tsize = strtoul ( value, &end, 10 );
00582         if ( *end ) {
00583                 DBGC ( tftp, "TFTP %p got invalid tsize \"%s\"\n",
00584                        tftp, value );
00585                 return -( EINVAL | ETFTP_INVALID_TSIZE );
00586         }
00587         DBGC ( tftp, "TFTP %p tsize=%ld\n", tftp, tftp->tsize );
00588 
00589         return 0;
00590 }

static int tftp_process_multicast ( struct tftp_request tftp,
const char *  value 
) [static]

Process TFTP "multicast" option.

Parameters:
tftp TFTP connection
value Option value
Return values:
rc Return status code

Definition at line 599 of file tftp.c.

References AF_INET, DBGC, EINVAL, ETFTP_MC_INVALID_IP, ETFTP_MC_INVALID_MC, ETFTP_MC_INVALID_PORT, ETFTP_MC_NO_MC, ETFTP_MC_NO_PORT, tftp_request::flags, htons, inet_aton(), inet_ntoa(), memcpy, ntohs, strchr(), strlen(), strtoul(), TFTP_FL_SEND_ACK, and tftp_reopen_mc().

00600                                                         {
00601         union {
00602                 struct sockaddr sa;
00603                 struct sockaddr_in sin;
00604         } socket;
00605         char buf[ strlen ( value ) + 1 ];
00606         char *addr;
00607         char *port;
00608         char *port_end;
00609         char *mc;
00610         char *mc_end;
00611         int rc;
00612 
00613         /* Split value into "addr,port,mc" fields */
00614         memcpy ( buf, value, sizeof ( buf ) );
00615         addr = buf;
00616         port = strchr ( addr, ',' );
00617         if ( ! port ) {
00618                 DBGC ( tftp, "TFTP %p multicast missing port,mc\n", tftp );
00619                 return -( EINVAL | ETFTP_MC_NO_PORT );
00620         }
00621         *(port++) = '\0';
00622         mc = strchr ( port, ',' );
00623         if ( ! mc ) {
00624                 DBGC ( tftp, "TFTP %p multicast missing mc\n", tftp );
00625                 return -( EINVAL | ETFTP_MC_NO_MC );
00626         }
00627         *(mc++) = '\0';
00628 
00629         /* Parse parameters */
00630         if ( strtoul ( mc, &mc_end, 0 ) == 0 )
00631                 tftp->flags &= ~TFTP_FL_SEND_ACK;
00632         if ( *mc_end ) {
00633                 DBGC ( tftp, "TFTP %p multicast invalid mc %s\n", tftp, mc );
00634                 return -( EINVAL | ETFTP_MC_INVALID_MC );
00635         }
00636         DBGC ( tftp, "TFTP %p is%s the master client\n",
00637                tftp, ( ( tftp->flags & TFTP_FL_SEND_ACK ) ? "" : " not" ) );
00638         if ( *addr && *port ) {
00639                 socket.sin.sin_family = AF_INET;
00640                 if ( inet_aton ( addr, &socket.sin.sin_addr ) == 0 ) {
00641                         DBGC ( tftp, "TFTP %p multicast invalid IP address "
00642                                "%s\n", tftp, addr );
00643                         return -( EINVAL | ETFTP_MC_INVALID_IP );
00644                 }
00645                 DBGC ( tftp, "TFTP %p multicast IP address %s\n",
00646                        tftp, inet_ntoa ( socket.sin.sin_addr ) );
00647                 socket.sin.sin_port = htons ( strtoul ( port, &port_end, 0 ) );
00648                 if ( *port_end ) {
00649                         DBGC ( tftp, "TFTP %p multicast invalid port %s\n",
00650                                tftp, port );
00651                         return -( EINVAL | ETFTP_MC_INVALID_PORT );
00652                 }
00653                 DBGC ( tftp, "TFTP %p multicast port %d\n",
00654                        tftp, ntohs ( socket.sin.sin_port ) );
00655                 if ( ( rc = tftp_reopen_mc ( tftp, &socket.sa ) ) != 0 )
00656                         return rc;
00657         }
00658 
00659         return 0;
00660 }

static int tftp_process_option ( struct tftp_request tftp,
const char *  name,
const char *  value 
) [static]

Process TFTP option.

Parameters:
tftp TFTP connection
name Option name
value Option value
Return values:
rc Return status code

Definition at line 691 of file tftp.c.

References DBGC, tftp_option::name, tftp_option::process, and strcasecmp().

Referenced by tftp_rx_oack().

00692                                                                        {
00693         struct tftp_option *option;
00694 
00695         for ( option = tftp_options ; option->name ; option++ ) {
00696                 if ( strcasecmp ( name, option->name ) == 0 )
00697                         return option->process ( tftp, value );
00698         }
00699 
00700         DBGC ( tftp, "TFTP %p received unknown option \"%s\" = \"%s\"\n",
00701                tftp, name, value );
00702 
00703         /* Unknown options should be silently ignored */
00704         return 0;
00705 }

static int tftp_rx_oack ( struct tftp_request tftp,
void *  buf,
size_t  len 
) [static]

Receive OACK.

Parameters:
tftp TFTP connection
buf Temporary data buffer
len Length of temporary data buffer
Return values:
rc Return status code

Definition at line 715 of file tftp.c.

References tftp_oack::data, DBGC, DBGC_HD, EINVAL, tftp_request::flags, name, strnlen(), tftp_done(), TFTP_FL_SIZEONLY, tftp_presize(), tftp_process_option(), tftp_send_error(), tftp_send_packet(), and tftp_request::tsize.

Referenced by tftp_rx().

00715                                                                              {
00716         struct tftp_oack *oack = buf;
00717         char *end = buf + len;
00718         char *name;
00719         char *value;
00720         char *next;
00721         int rc = 0;
00722 
00723         /* Sanity check */
00724         if ( len < sizeof ( *oack ) ) {
00725                 DBGC ( tftp, "TFTP %p received underlength OACK packet "
00726                        "length %zd\n", tftp, len );
00727                 rc = -EINVAL;
00728                 goto done;
00729         }
00730 
00731         /* Process each option in turn */
00732         for ( name = oack->data ; name < end ; name = next ) {
00733 
00734                 /* Parse option name and value
00735                  *
00736                  * We treat parsing errors as non-fatal, because there
00737                  * exists at least one TFTP server (IBM Tivoli PXE
00738                  * Server 5.1.0.3) that has been observed to send
00739                  * malformed OACKs containing trailing garbage bytes.
00740                  */
00741                 value = ( name + strnlen ( name, ( end - name ) ) + 1 );
00742                 if ( value > end ) {
00743                         DBGC ( tftp, "TFTP %p received OACK with malformed "
00744                                "option name:\n", tftp );
00745                         DBGC_HD ( tftp, oack, len );
00746                         break;
00747                 }
00748                 if ( value == end ) {
00749                         DBGC ( tftp, "TFTP %p received OACK missing value "
00750                                "for option \"%s\"\n", tftp, name );
00751                         DBGC_HD ( tftp, oack, len );
00752                         break;
00753                 }
00754                 next = ( value + strnlen ( value, ( end - value ) ) + 1 );
00755                 if ( next > end ) {
00756                         DBGC ( tftp, "TFTP %p received OACK with malformed "
00757                                "value for option \"%s\":\n", tftp, name );
00758                         DBGC_HD ( tftp, oack, len );
00759                         break;
00760                 }
00761 
00762                 /* Process option */
00763                 if ( ( rc = tftp_process_option ( tftp, name, value ) ) != 0 )
00764                         goto done;
00765         }
00766 
00767         /* Process tsize information, if available */
00768         if ( tftp->tsize ) {
00769                 if ( ( rc = tftp_presize ( tftp, tftp->tsize ) ) != 0 )
00770                         goto done;
00771         }
00772 
00773         /* Abort request if only trying to determine file size */
00774         if ( tftp->flags & TFTP_FL_SIZEONLY ) {
00775                 rc = 0;
00776                 tftp_send_error ( tftp, 0, "TFTP Aborted" );
00777                 tftp_done ( tftp, rc );
00778                 return rc;
00779         }
00780 
00781         /* Request next data block */
00782         tftp_send_packet ( tftp );
00783 
00784  done:
00785         if ( rc )
00786                 tftp_done ( tftp, rc );
00787         return rc;
00788 }

static int tftp_rx_data ( struct tftp_request tftp,
struct io_buffer iobuf 
) [static]

Receive DATA.

Parameters:
tftp TFTP connection
iobuf I/O buffer
Return values:
rc Return status code
Takes ownership of I/O buffer.

Definition at line 799 of file tftp.c.

References tftp_request::bitmap, bitmap_first_gap(), bitmap_full(), bitmap_set(), tftp_request::blksize, tftp_data::block, io_buffer::data, tftp_data::data, DBGC, EINVAL, ENOTSUP, tftp_request::flags, free_iob(), iob_disown, iob_len(), iob_pull, memset(), ntohs, xfer_metadata::offset, offset, SEEK_SET, strerror(), tftp_done(), TFTP_FL_SIZEONLY, tftp_presize(), tftp_send_error(), tftp_send_packet(), xfer_metadata::whence, tftp_request::xfer, and xfer_deliver_iob_meta().

Referenced by tftp_rx().

00800                                                     {
00801         struct tftp_data *data = iobuf->data;
00802         struct xfer_metadata meta;
00803         unsigned int block;
00804         off_t offset;
00805         size_t data_len;
00806         int rc;
00807 
00808         if ( tftp->flags & TFTP_FL_SIZEONLY ) {
00809                 /* If we get here then server doesn't support SIZE option */
00810                 rc = -ENOTSUP;
00811                 tftp_send_error ( tftp, 0, "TFTP Aborted" );
00812                 goto done;
00813         }
00814 
00815         /* Sanity check */
00816         if ( iob_len ( iobuf ) < sizeof ( *data ) ) {
00817                 DBGC ( tftp, "TFTP %p received underlength DATA packet "
00818                        "length %zd\n", tftp, iob_len ( iobuf ) );
00819                 rc = -EINVAL;
00820                 goto done;
00821         }
00822 
00823         /* Calculate block number */
00824         block = ( ( bitmap_first_gap ( &tftp->bitmap ) + 1 ) & ~0xffff );
00825         if ( data->block == 0 && block == 0 ) {
00826                 DBGC ( tftp, "TFTP %p received data block 0\n", tftp );
00827                 rc = -EINVAL;
00828                 goto done;
00829         }
00830         block += ( ntohs ( data->block ) - 1 );
00831 
00832         /* Extract data */
00833         offset = ( block * tftp->blksize );
00834         iob_pull ( iobuf, sizeof ( *data ) );
00835         data_len = iob_len ( iobuf );
00836         if ( data_len > tftp->blksize ) {
00837                 DBGC ( tftp, "TFTP %p received overlength DATA packet "
00838                        "length %zd\n", tftp, data_len );
00839                 rc = -EINVAL;
00840                 goto done;
00841         }
00842 
00843         /* Deliver data */
00844         memset ( &meta, 0, sizeof ( meta ) );
00845         meta.whence = SEEK_SET;
00846         meta.offset = offset;
00847         if ( ( rc = xfer_deliver_iob_meta ( &tftp->xfer, iob_disown ( iobuf ),
00848                                             &meta ) ) != 0 ) {
00849                 DBGC ( tftp, "TFTP %p could not deliver data: %s\n",
00850                        tftp, strerror ( rc ) );
00851                 goto done;
00852         }
00853 
00854         /* Ensure block bitmap is ready */
00855         if ( ( rc = tftp_presize ( tftp, ( offset + data_len ) ) ) != 0 )
00856                 goto done;
00857 
00858         /* Mark block as received */
00859         bitmap_set ( &tftp->bitmap, block );
00860 
00861         /* Acknowledge block */
00862         tftp_send_packet ( tftp );
00863 
00864         /* If all blocks have been received, finish. */
00865         if ( bitmap_full ( &tftp->bitmap ) )
00866                 tftp_done ( tftp, 0 );
00867 
00868  done:
00869         free_iob ( iobuf );
00870         if ( rc )
00871                 tftp_done ( tftp, rc );
00872         return rc;
00873 }

static int tftp_rx_error ( struct tftp_request tftp,
void *  buf,
size_t  len 
) [static]

Receive ERROR.

Parameters:
tftp TFTP connection
buf Temporary data buffer
len Length of temporary data buffer
Return values:
rc Return status code

Definition at line 890 of file tftp.c.

References DBGC, EINVAL, ENOTSUP, tftp_error::errcode, tftp_error::errmsg, ntohs, tftp_done(), and tftp_errors.

Referenced by tftp_rx().

00890                                                                               {
00891         struct tftp_error *error = buf;
00892         unsigned int err;
00893         int rc = 0;
00894 
00895         /* Sanity check */
00896         if ( len < sizeof ( *error ) ) {
00897                 DBGC ( tftp, "TFTP %p received underlength ERROR packet "
00898                        "length %zd\n", tftp, len );
00899                 return -EINVAL;
00900         }
00901 
00902         DBGC ( tftp, "TFTP %p received ERROR packet with code %d, message "
00903                "\"%s\"\n", tftp, ntohs ( error->errcode ), error->errmsg );
00904         
00905         /* Determine final operation result */
00906         err = ntohs ( error->errcode );
00907         if ( err < ( sizeof ( tftp_errors ) / sizeof ( tftp_errors[0] ) ) )
00908                 rc = -tftp_errors[err];
00909         if ( ! rc )
00910                 rc = -ENOTSUP;
00911 
00912         /* Close TFTP request */
00913         tftp_done ( tftp, rc );
00914 
00915         return 0;
00916 }

static int tftp_rx ( struct tftp_request tftp,
struct io_buffer iobuf,
struct xfer_metadata meta 
) [static]

Receive new data.

Parameters:
tftp TFTP connection
iobuf I/O buffer
meta Transfer metadata
Return values:
rc Return status code

Definition at line 926 of file tftp.c.

References io_buffer::data, DBGC, EINVAL, free_iob(), htons, iob_disown, iob_len(), memcmp(), memcpy, ntohs, tftp_common::opcode, tftp_request::peer, xfer_metadata::src, sockaddr_tcpip::st_family, sockaddr_tcpip::st_port, TFTP_DATA, TFTP_ERROR, TFTP_OACK, tftp_rx_data(), tftp_rx_error(), and tftp_rx_oack().

Referenced by tftp_mc_socket_deliver_iob(), and tftp_socket_deliver_iob().

00928                                                   {
00929         struct sockaddr_tcpip *st_src;
00930         struct tftp_common *common = iobuf->data;
00931         size_t len = iob_len ( iobuf );
00932         int rc = -EINVAL;
00933         
00934         /* Sanity checks */
00935         if ( len < sizeof ( *common ) ) {
00936                 DBGC ( tftp, "TFTP %p received underlength packet length "
00937                        "%zd\n", tftp, len );
00938                 goto done;
00939         }
00940         if ( ! meta->src ) {
00941                 DBGC ( tftp, "TFTP %p received packet without source port\n",
00942                        tftp );
00943                 goto done;
00944         }
00945 
00946         /* Filter by TID.  Set TID on first response received */
00947         st_src = ( struct sockaddr_tcpip * ) meta->src;
00948         if ( ! tftp->peer.st_family ) {
00949                 memcpy ( &tftp->peer, st_src, sizeof ( tftp->peer ) );
00950                 DBGC ( tftp, "TFTP %p using remote port %d\n", tftp,
00951                        ntohs ( tftp->peer.st_port ) );
00952         } else if ( memcmp ( &tftp->peer, st_src,
00953                              sizeof ( tftp->peer ) ) != 0 ) {
00954                 DBGC ( tftp, "TFTP %p received packet from wrong source (got "
00955                        "%d, wanted %d)\n", tftp, ntohs ( st_src->st_port ),
00956                        ntohs ( tftp->peer.st_port ) );
00957                 goto done;
00958         }
00959 
00960         switch ( common->opcode ) {
00961         case htons ( TFTP_OACK ):
00962                 rc = tftp_rx_oack ( tftp, iobuf->data, len );
00963                 break;
00964         case htons ( TFTP_DATA ):
00965                 rc = tftp_rx_data ( tftp, iob_disown ( iobuf ) );
00966                 break;
00967         case htons ( TFTP_ERROR ):
00968                 rc = tftp_rx_error ( tftp, iobuf->data, len );
00969                 break;
00970         default:
00971                 DBGC ( tftp, "TFTP %p received strange packet type %d\n",
00972                        tftp, ntohs ( common->opcode ) );
00973                 break;
00974         };
00975 
00976  done:
00977         free_iob ( iobuf );
00978         return rc;
00979 }

static int tftp_socket_deliver_iob ( struct xfer_interface socket,
struct io_buffer iobuf,
struct xfer_metadata meta 
) [static]

Receive new data via socket.

Parameters:
socket Transport layer interface
iobuf I/O buffer
meta Transfer metadata
Return values:
rc Return status code

Definition at line 989 of file tftp.c.

References container_of, tftp_request::flags, TFTP_FL_SEND_ACK, and tftp_rx().

00991                                                                   {
00992         struct tftp_request *tftp =
00993                 container_of ( socket, struct tftp_request, socket );
00994 
00995         /* Enable sending ACKs when we receive a unicast packet.  This
00996          * covers three cases:
00997          *
00998          * 1. Standard TFTP; we should always send ACKs, and will
00999          *    always receive a unicast packet before we need to send the
01000          *    first ACK.
01001          *
01002          * 2. RFC2090 multicast TFTP; the only unicast packets we will
01003          *    receive are the OACKs; enable sending ACKs here (before
01004          *    processing the OACK) and disable it when processing the
01005          *    multicast option if we are not the master client.
01006          *
01007          * 3. MTFTP; receiving a unicast datagram indicates that we
01008          *    are the "master client" and should send ACKs.
01009          */
01010         tftp->flags |= TFTP_FL_SEND_ACK;
01011 
01012         return tftp_rx ( tftp, iobuf, meta );
01013 }

static int tftp_mc_socket_deliver_iob ( struct xfer_interface mc_socket,
struct io_buffer iobuf,
struct xfer_metadata meta 
) [static]

Receive new data via multicast socket.

Parameters:
mc_socket Multicast transport layer interface
iobuf I/O buffer
meta Transfer metadata
Return values:
rc Return status code

Definition at line 1033 of file tftp.c.

References container_of, and tftp_rx().

01035                                                                      {
01036         struct tftp_request *tftp =
01037                 container_of ( mc_socket, struct tftp_request, mc_socket );
01038 
01039         return tftp_rx ( tftp, iobuf, meta );
01040 }

static void tftp_xfer_close ( struct xfer_interface xfer,
int  rc 
) [static]

Close TFTP data transfer interface.

Parameters:
xfer Data transfer interface
rc Reason for close

Definition at line 1058 of file tftp.c.

References container_of, DBGC, strerror(), and tftp_done().

01058                                                                     {
01059         struct tftp_request *tftp =
01060                 container_of ( xfer, struct tftp_request, xfer );
01061 
01062         DBGC ( tftp, "TFTP %p interface closed: %s\n",
01063                tftp, strerror ( rc ) );
01064 
01065         tftp_done ( tftp, rc );
01066 }

static size_t tftp_xfer_window ( struct xfer_interface xfer  )  [static]

Check flow control window.

Parameters:
xfer Data transfer interface
Return values:
len Length of window

Definition at line 1074 of file tftp.c.

References tftp_request::blksize, and container_of.

01074                                                                {
01075         struct tftp_request *tftp =
01076                 container_of ( xfer, struct tftp_request, xfer );
01077 
01078         /* We abuse this data-xfer method to convey the blocksize to
01079          * the caller.  This really should be done using some kind of
01080          * stat() method, but we don't yet have the facility to do
01081          * that.
01082          */
01083         return tftp->blksize;
01084 }

static int tftp_core_open ( struct xfer_interface xfer,
struct uri uri,
unsigned int  default_port,
struct sockaddr multicast,
unsigned int  flags 
) [static]

Initiate TFTP/TFTM/MTFTP download.

Parameters:
xfer Data transfer interface
uri Uniform Resource Identifier
Return values:
rc Return status code

Definition at line 1103 of file tftp.c.

References tftp_request::blksize, DBGC, EINVAL, ENOMEM, retry_timer::expired, tftp_request::flags, refcnt::free, uri::host, tftp_request::mc_socket, uri::path, tftp_request::port, ref_put(), tftp_request::refcnt, tftp_request::socket, start_timer_nodelay(), strerror(), TFTP_DEFAULT_BLKSIZE, tftp_done(), tftp_free(), tftp_reopen(), tftp_reopen_mc(), tftp_timer_expired(), tftp_request::timer, tftp_request::uri, uri_port(), tftp_request::xfer, xfer_init(), and zalloc().

Referenced by mtftp_open(), tftm_open(), tftp_open(), and tftpsize_open().

01106                                                  {
01107         struct tftp_request *tftp;
01108         int rc;
01109 
01110         /* Sanity checks */
01111         if ( ! uri->host )
01112                 return -EINVAL;
01113         if ( ! uri->path )
01114                 return -EINVAL;
01115 
01116         /* Allocate and populate TFTP structure */
01117         tftp = zalloc ( sizeof ( *tftp ) );
01118         if ( ! tftp )
01119                 return -ENOMEM;
01120         tftp->refcnt.free = tftp_free;
01121         xfer_init ( &tftp->xfer, &tftp_xfer_operations, &tftp->refcnt );
01122         tftp->uri = uri_get ( uri );
01123         xfer_init ( &tftp->socket, &tftp_socket_operations, &tftp->refcnt );
01124         xfer_init ( &tftp->mc_socket, &tftp_mc_socket_operations,
01125                     &tftp->refcnt );
01126         tftp->blksize = TFTP_DEFAULT_BLKSIZE;
01127         tftp->flags = flags;
01128         tftp->timer.expired = tftp_timer_expired;
01129 
01130         /* Open socket */
01131         tftp->port = uri_port ( tftp->uri, default_port );
01132         if ( ( rc = tftp_reopen ( tftp ) ) != 0 )
01133                 goto err;
01134 
01135         /* Open multicast socket */
01136         if ( multicast ) {
01137                 if ( ( rc = tftp_reopen_mc ( tftp, multicast ) ) != 0 )
01138                         goto err;
01139         }
01140 
01141         /* Start timer to initiate RRQ */
01142         start_timer_nodelay ( &tftp->timer );
01143 
01144         /* Attach to parent interface, mortalise self, and return */
01145         xfer_plug_plug ( &tftp->xfer, xfer );
01146         ref_put ( &tftp->refcnt );
01147         return 0;
01148 
01149  err:
01150         DBGC ( tftp, "TFTP %p could not create request: %s\n",
01151                tftp, strerror ( rc ) );
01152         tftp_done ( tftp, rc );
01153         ref_put ( &tftp->refcnt );
01154         return rc;
01155 }

static int tftp_open ( struct xfer_interface xfer,
struct uri uri 
) [static]

Initiate TFTP download.

Parameters:
xfer Data transfer interface
uri Uniform Resource Identifier
Return values:
rc Return status code

Definition at line 1164 of file tftp.c.

References NULL, tftp_core_open(), TFTP_FL_RRQ_SIZES, and TFTP_PORT.

01164                                                                       {
01165         return tftp_core_open ( xfer, uri, TFTP_PORT, NULL,
01166                                 TFTP_FL_RRQ_SIZES );
01167 
01168 }

static int tftpsize_open ( struct xfer_interface xfer,
struct uri uri 
) [static]

Initiate TFTP-size request.

Parameters:
xfer Data transfer interface
uri Uniform Resource Identifier
Return values:
rc Return status code

Definition at line 1183 of file tftp.c.

References NULL, tftp_core_open(), TFTP_FL_RRQ_SIZES, TFTP_FL_SIZEONLY, and TFTP_PORT.

01183                                                                           {
01184         return tftp_core_open ( xfer, uri, TFTP_PORT, NULL,
01185                                 ( TFTP_FL_RRQ_SIZES |
01186                                   TFTP_FL_SIZEONLY ) );
01187 
01188 }

static int tftm_open ( struct xfer_interface xfer,
struct uri uri 
) [static]

Initiate TFTM download.

Parameters:
xfer Data transfer interface
uri Uniform Resource Identifier
Return values:
rc Return status code

Definition at line 1203 of file tftp.c.

References NULL, tftp_core_open(), TFTP_FL_RRQ_MULTICAST, TFTP_FL_RRQ_SIZES, and TFTP_PORT.

01203                                                                       {
01204         return tftp_core_open ( xfer, uri, TFTP_PORT, NULL,
01205                                 ( TFTP_FL_RRQ_SIZES |
01206                                   TFTP_FL_RRQ_MULTICAST ) );
01207 
01208 }

static int mtftp_open ( struct xfer_interface xfer,
struct uri uri 
) [static]

Initiate MTFTP download.

Parameters:
xfer Data transfer interface
uri Uniform Resource Identifier
Return values:
rc Return status code

Definition at line 1223 of file tftp.c.

References MTFTP_PORT, tftp_core_open(), and TFTP_FL_MTFTP_RECOVERY.

01223                                                                        {
01224         return tftp_core_open ( xfer, uri, MTFTP_PORT,
01225                                 ( struct sockaddr * ) &tftp_mtftp_socket,
01226                                 TFTP_FL_MTFTP_RECOVERY );
01227 }

static int tftp_apply_settings ( void   )  [static]

Apply TFTP configuration settings.

Return values:
rc Return status code

Definition at line 1255 of file tftp.c.

References churi(), ENOMEM, fetch_ipv4_setting(), inet_ntoa(), NULL, parse_uri(), in_addr::s_addr, and snprintf().

01255                                         {
01256         static struct in_addr tftp_server = { 0 };
01257         struct in_addr last_tftp_server;
01258         char uri_string[32];
01259         struct uri *uri;
01260 
01261         /* Retrieve TFTP server setting */
01262         last_tftp_server = tftp_server;
01263         fetch_ipv4_setting ( NULL, &next_server_setting, &tftp_server );
01264 
01265         /* If TFTP server setting has changed, set the current working
01266          * URI to match.  Do it only when the TFTP server has changed
01267          * to try to minimise surprises to the user, who probably
01268          * won't expect the CWURI to change just because they updated
01269          * an unrelated setting and triggered all the settings
01270          * applicators.
01271          */
01272         if ( tftp_server.s_addr != last_tftp_server.s_addr ) {
01273                 snprintf ( uri_string, sizeof ( uri_string ),
01274                            "tftp://%s/", inet_ntoa ( tftp_server ) );
01275                 uri = parse_uri ( uri_string );
01276                 if ( ! uri )
01277                         return -ENOMEM;
01278                 churi ( uri );
01279                 uri_put ( uri );
01280         }
01281 
01282         return 0;
01283 }


Variable Documentation

unsigned int tftp_request_blksize = TFTP_MAX_BLKSIZE [static]

TFTP requested blocksize.

This is treated as a global configuration parameter.

Definition at line 282 of file tftp.c.

Referenced by tftp_send_rrq(), and tftp_set_request_blksize().

struct sockaddr_in tftp_mtftp_socket [static]

Initial value:

 {
        .sin_family = AF_INET,
        .sin_addr.s_addr = htonl ( 0xefff0101 ),
        .sin_port = htons ( 3001 ),
}
MTFTP multicast receive address.

This is treated as a global configuration parameter.

Definition at line 300 of file tftp.c.

struct tftp_option tftp_options[] [static]

Initial value:

 {
        { "blksize", tftp_process_blksize },
        { "tsize", tftp_process_tsize },
        { "multicast", tftp_process_multicast },
        { NULL, NULL }
}
Recognised TFTP options.

Definition at line 676 of file tftp.c.

const int tftp_errors[] [static]

Initial value:

Translation between TFTP errors and internal error numbers.

Definition at line 876 of file tftp.c.

Referenced by tftp_rx_error().

Initial value:

 {
        .close          = ignore_xfer_close,
        .vredirect      = xfer_vreopen,
        .window         = unlimited_xfer_window,
        .alloc_iob      = default_xfer_alloc_iob,
        .deliver_iob    = tftp_socket_deliver_iob,
        .deliver_raw    = xfer_deliver_as_iob,
}
TFTP socket operations.

Definition at line 1016 of file tftp.c.

Initial value:

 {
        .close          = ignore_xfer_close,
        .vredirect      = xfer_vreopen,
        .window         = unlimited_xfer_window,
        .alloc_iob      = default_xfer_alloc_iob,
        .deliver_iob    = tftp_mc_socket_deliver_iob,
        .deliver_raw    = xfer_deliver_as_iob,
}
TFTP multicast socket operations.

Definition at line 1043 of file tftp.c.

Initial value:

 {
        .close          = tftp_xfer_close,
        .vredirect      = ignore_xfer_vredirect,
        .window         = tftp_xfer_window,
        .alloc_iob      = default_xfer_alloc_iob,
        .deliver_iob    = xfer_deliver_as_raw,
        .deliver_raw    = ignore_xfer_deliver_raw,
}
TFTP data transfer interface operations.

Definition at line 1087 of file tftp.c.

struct uri_opener mtftp_uri_opener __uri_opener [read]

Initial value:

 {
        .scheme = "tftp",
        .open   = tftp_open,
}
TFTP URI opener.

MTFTP URI opener.

TFTM URI opener.

Definition at line 1171 of file tftp.c.

struct settings_applicator tftp_settings_applicator __settings_applicator

Initial value:

 {
        .apply = tftp_apply_settings,
}
TFTP settings applicator.

Definition at line 1286 of file tftp.c.


Generated on Tue Apr 6 20:01:57 2010 for gPXE by  doxygen 1.5.7.1