#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. | |
Definition in file tftp.c.
| #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.
Definition at line 141 of file tftp.c.
Referenced by tftp_timer_expired().
| anonymous enum |
TFTP request flags.
| 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 };
| FILE_LICENCE | ( | GPL2_OR_LATER | ) |
| FEATURE | ( | FEATURE_PROTOCOL | , | |
| "TFTP" | , | |||
| DHCP_EB_FEATURE_TFTP | , | |||
| 1 | ||||
| ) |
| static void tftp_free | ( | struct refcnt * | refcnt | ) | [static] |
Free TFTP request.
| 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.
| 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.
| tftp | TFTP connection |
| 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.
| tftp | TFTP connection | |
| local | Local socket address |
| 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.
| tftp | TFTP connection | |
| filesize | Known minimum file size |
| 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.
| 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.
| 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.
| 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.
| tftp | TFTP connection |
| 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.
| tftp | TFTP connection |
| 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).
| tftp | TFTP connection | |
| errcode | TFTP error code | |
| errmsg | Error message string |
| 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.
| tftp | TFTP connection |
| 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.
| 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.
| tftp | TFTP connection | |
| value | Option value |
| 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.
| tftp | TFTP connection | |
| value | Option value |
| 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.
| tftp | TFTP connection | |
| value | Option value |
| 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.
| tftp | TFTP connection | |
| name | Option name | |
| value | Option value |
| 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.
| tftp | TFTP connection | |
| buf | Temporary data buffer | |
| len | Length of temporary data buffer |
| 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.
| tftp | TFTP connection | |
| iobuf | I/O buffer |
| rc | Return status code |
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.
| tftp | TFTP connection | |
| buf | Temporary data buffer | |
| len | Length of temporary data buffer |
| 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.
| tftp | TFTP connection | |
| iobuf | I/O buffer | |
| meta | Transfer metadata |
| 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.
| socket | Transport layer interface | |
| iobuf | I/O buffer | |
| meta | Transfer metadata |
| 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.
| mc_socket | Multicast transport layer interface | |
| iobuf | I/O buffer | |
| meta | Transfer metadata |
| 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.
| 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.
| xfer | Data transfer interface |
| 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.
| 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.
| 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.
| 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.
| 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.
| 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.
| 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 }
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] |
struct tftp_option tftp_options[] [static] |
Initial value:
{
{ "blksize", tftp_process_blksize },
{ "tsize", tftp_process_tsize },
{ "multicast", tftp_process_multicast },
{ NULL, NULL }
}
const int tftp_errors[] [static] |
Initial value:
{
[TFTP_ERR_FILE_NOT_FOUND] = ENOENT,
[TFTP_ERR_ACCESS_DENIED] = EACCES,
[TFTP_ERR_ILLEGAL_OP] = ENOTSUP,
}
Definition at line 876 of file tftp.c.
Referenced by tftp_rx_error().
struct xfer_interface_operations tftp_socket_operations [static] |
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,
}
struct xfer_interface_operations tftp_mc_socket_operations [static] |
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,
}
struct xfer_interface_operations tftp_xfer_operations [static] |
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,
}
struct uri_opener mtftp_uri_opener __uri_opener [read] |
| struct settings_applicator tftp_settings_applicator __settings_applicator |
1.5.7.1