2 #include "tcp.h" /* for struct tcphdr */
10 * await_reply() filter for TFTP packets
12 * @v ptr Pointer to a struct tftp_state
13 * @v tftp_state::server::sin_addr TFTP server IP address
14 * @v tftp_state::client::sin_addr Client multicast IP address, or 0.0.0.0
15 * @v tftp_state::client::sin_port Client UDP port
18 * @ret True This is our TFTP packet
19 * @ret False This is not one of our TFTP packets
21 * Wait for a TFTP packet that is part of the current connection
22 * (i.e. comes from the TFTP server, has the correct destination port,
23 * and is addressed either to our IP address or to our multicast
26 * Use await_tftp() in code such as
30 * if ( await_reply ( await_tftp, 0, &tftp_state, timeout ) ) {
36 static int await_tftp ( int ival __unused, void *ptr,
37 unsigned short ptype __unused, struct iphdr *ip,
38 struct udphdr *udp, struct tcphdr *tcp __unused ) {
39 struct tftp_state *state = ptr;
41 /* Must have valid UDP (and, therefore, also IP) headers */
43 DBG2 ( "TFTPCORE: not UDP\n" );
46 /* Packet must come from the TFTP server */
47 if ( ip->src.s_addr != state->server.sin_addr.s_addr ) {
48 DBG2 ( "TFTPCORE: from %@, not from TFTP server %@\n",
49 ip->src.s_addr, state->server.sin_addr.s_addr );
52 /* Packet must be addressed to the correct UDP port */
53 if ( ntohs ( udp->dest ) != state->client.sin_port ) {
54 DBG2 ( "TFTPCORE: to UDP port %d, not to TFTP port %d\n",
55 ntohs ( udp->dest ), state->client.sin_port );
58 /* Packet must be addressed to us, or to our multicast
59 * listening address (if we have one).
61 if ( ! ( ( ip->dest.s_addr == arptable[ARP_CLIENT].ipaddr.s_addr ) ||
62 ( ( state->client.sin_addr.s_addr ) &&
63 ( ip->dest.s_addr == state->client.sin_addr.s_addr ) ) ) ) {
64 DBG2 ( "TFTPCORE: to %@, not to %@ (or %@)\n",
65 ip->dest.s_addr, arptable[ARP_CLIENT].ipaddr.s_addr,
66 state->client.sin_addr.s_addr );
73 * Retrieve a TFTP packet
75 * @v state TFTP transfer state
76 * @v tftp_state::server::sin_addr TFTP server IP address
77 * @v tftp_state::client::sin_addr Client multicast IP address, or 0.0.0.0
78 * @v tftp_state::client::sin_port Client UDP port
79 * @v timeout Time to wait for a response
80 * @ret True Received a non-error response
81 * @ret False Received error response / no response
82 * @ret *reply The server's response, if any
83 * @err #PXENV_STATUS_TFTP_READ_TIMEOUT No response received in time
84 * @err other As set by tftp_set_errno()
86 * Retrieve the next packet sent by the TFTP server, if any is sent
87 * within the specified timeout period. The packet is returned via
88 * #reply. If no packet is received within the timeout period, a NULL
89 * value will be stored in #reply.
91 * If the response from the server is a TFTP ERROR packet, tftp_get()
92 * will return False and #errno will be set accordingly.
94 * You can differentiate between "received no response" and "received
95 * an error response" by checking #reply; if #reply is NULL then no
96 * response was received.
98 int tftp_get ( struct tftp_state *state, long timeout,
99 union tftp_any **reply ) {
103 if ( ! await_reply ( await_tftp, 0, state, timeout ) ) {
104 errno = PXENV_STATUS_TFTP_READ_TIMEOUT;
108 *reply = ( union tftp_any * ) &nic.packet[ETH_HLEN];
109 DBG ( "TFTPCORE: got reply (type %d)\n",
110 ntohs ( (*reply)->common.opcode ) );
111 if ( ntohs ( (*reply)->common.opcode ) == TFTP_ERROR ){
112 tftp_set_errno ( &(*reply)->error );
119 * Issue a TFTP open request (RRQ)
121 * @v state TFTP transfer state
122 * @v tftp_state::server::sin_addr TFTP server IP address
123 * @v tftp_state::server::sin_port TFTP server UDP port, or 0
124 * @v tftp_state::client::sin_addr Client multicast IP address, or 0.0.0.0
125 * @v tftp_state::client::sin_port Client UDP port, or 0
126 * @v tftp_state::blksize Requested blksize, or 0
127 * @v filename File name
128 * @v multicast Enable/disable rfc2090 multicast TFTP
129 * @ret True Received a non-error response
130 * @ret False Received error response / no response
131 * @ret tftp_state::server::sin_port TFTP server UDP port
132 * @ret tftp_state::client::sin_port Client UDP port
133 * @ret tftp_state::blksize Always #TFTP_DEFAULT_BLKSIZE
134 * @ret *reply The server's response, if any
135 * @err #PXENV_STATUS_TFTP_OPEN_TIMEOUT TFTP open timed out
136 * @err other As returned by udp_transmit()
137 * @err other As set by tftp_set_errno()
139 * Send a TFTP/TFTM/MTFTP RRQ (read request) to a TFTP server, and
140 * return the server's reply (which may be an OACK, DATA or ERROR
141 * packet). The server's reply will not be acknowledged, or processed
144 * If tftp_state::server::sin_port is 0, the standard TFTP server port
145 * (#TFTP_PORT) will be used.
147 * If tftp_state::client::sin_addr is not 0.0.0.0, it will be used as
148 * a multicast listening address for replies from the TFTP server.
150 * If tftp_state::client::sin_port is 0, the standard mechanism of
151 * using a new, unique port number for each TFTP request will be used.
153 * For the various different types of TFTP server, you should treat
154 * tftp_state::client as follows:
156 * - Standard TFTP server: set tftp_state::client::sin_addr to
157 * 0.0.0.0 and tftp_state::client::sin_port to 0. tftp_open()
158 * will set tftp_state::client::sin_port to the assigned local UDP
161 * - TFTM server: set tftp_state::client::sin_addr to 0.0.0.0 and
162 * tftp_state::client::sin_port to 0. tftp_open() will set
163 * tftp_state::client::sin_port to the assigned local UDP port.
164 * (Your call to tftp_process_opts() will then overwrite both
165 * tftp_state::client::sin_addr and tftp_state::client::sin_port
166 * with the values return in the OACK packet.)
168 * - MTFTP server: set tftp_state::client::sin_addr to the client
169 * multicast address and tftp_state::client::sin_port to the
170 * client multicast port (both of which must be previously known,
171 * e.g. provided by a DHCP server). tftp_open() will not alter
174 * If tftp_state::blksize is 0, the maximum blocksize
175 * (#TFTP_MAX_BLKSIZE) will be requested.
177 * On exit, tftp_state::blksize will always contain
178 * #TFTP_DEFAULT_BLKSIZE, since this is the blocksize value that must
179 * be assumed until the OACK packet is processed (by a subsequent call
180 * to tftp_process_opts()).
182 * tftp_state::server::sin_port will be set to the UDP port from which
183 * the server's response originated. This may or may not be the port
184 * to which the open request was sent.
186 * The options "blksize" and "tsize" will always be appended to a TFTP
187 * open request. The option "multicast" will be appended to the
188 * request if #multicast is True. Servers that do not understand any
189 * of these options should simply ignore them.
191 * tftp_open() will not automatically join or leave multicast groups;
192 * the caller is responsible for calling join_group() and
193 * leave_group() at appropriate times.
195 * If the response from the server is a TFTP ERROR packet, tftp_open()
196 * will return False and #errno will be set accordingly.
198 int tftp_open ( struct tftp_state *state, const char *filename,
199 union tftp_any **reply, int multicast ) {
200 static unsigned short lport = 2000; /* local port */
207 /* Flush receive queue */
210 /* Default to blksize of TFTP_MAX_BLKSIZE if none specified */
211 if ( ! state->blksize )
212 state->blksize = TFTP_MAX_BLKSIZE;
214 /* Use default TFTP server port if none specified */
215 if ( ! state->server.sin_port )
216 state->server.sin_port = TFTP_PORT;
218 /* Determine whether or not to use lport */
219 fixed_lport = state->client.sin_port;
222 rrq.opcode = htons ( TFTP_RRQ );
224 p += sprintf ( p, "%s%coctet%cblksize%c%d%ctsize%c0",
225 filename, 0, 0, 0, state->blksize, 0, 0 ) + 1;
227 p += sprintf ( p, "multicast%c", 0 ) + 1;
229 rrqlen = ( p - ( char * ) &rrq );
231 /* Set negotiated blksize to default value */
232 state->blksize = TFTP_DEFAULT_BLKSIZE;
234 /* Nullify received packet pointer */
237 /* Transmit RRQ until we get a response */
238 for ( retry = 0 ; retry < MAX_TFTP_RETRIES ; retry++ ) {
239 long timeout = rfc2131_sleep_interval ( TIMEOUT, retry );
241 /* Set client UDP port, if not already fixed */
243 state->client.sin_port = ++lport;
246 DBG ( "TFTPCORE: requesting %@:%d/%s from port %d\n",
247 state->server.sin_addr.s_addr, state->server.sin_port,
248 rrq.data, state->client.sin_port );
249 if ( ! udp_transmit ( state->server.sin_addr.s_addr,
250 state->client.sin_port,
251 state->server.sin_port,
255 /* Wait for response */
256 if ( tftp_get ( state, timeout, reply ) ) {
257 /* We got a non-error response */
258 state->server.sin_port
259 = ntohs ( (*reply)->common.udp.src );
260 DBG ( "TFTP server is at %@:%d\n",
261 state->server.sin_addr.s_addr,
262 state->server.sin_port );
266 /* We got an error response; abort */
271 DBG ( "TFTPCORE: open request timed out\n" );
272 errno = PXENV_STATUS_TFTP_OPEN_TIMEOUT;
277 * Process a TFTP OACK packet
279 * @v state TFTP transfer state
280 * @v oack The TFTP OACK packet
281 * @ret True Options were processed successfully
282 * @ret False Options were not processed successfully
283 * @ret tftp_state::blksize Negotiated blksize
284 * @ret tftp_state::tsize File size (if known), or 0
285 * @ret tftp_state::client::sin_addr Client multicast IP address, or 0.0.0.0
286 * @ret tftp_state::client::sin_port Client UDP port
287 * @ret tftp_state::master Client is master
288 * @err EINVAL An invalid option value was encountered
290 * Process the options returned by the TFTP server in an rfc2347 OACK
291 * packet. The options "blksize" (rfc2348), "tsize" (rfc2349) and
292 * "multicast" (rfc2090) are recognised and processed; any other
293 * options are silently ignored.
295 * Where an option is not present in the OACK packet, the
296 * corresponding field(s) in #state will be left unaltered.
298 * Calling tftp_process_opts() does not send an acknowledgement for
299 * the OACK packet; this is the responsibility of the caller.
301 * @note If the "blksize" option is not present, tftp_state::blksize
302 * will @b not be implicitly set to #TFTP_DEFAULT_BLKSIZE. However,
303 * since tftp_open() always sets tftp_state::blksize to
304 * #TFTP_DEFAULT_BLKSIZE before returning, you probably don't need to
307 int tftp_process_opts ( struct tftp_state *state, struct tftp_oack *oack ) {
311 DBG ( "TFTPCORE: processing OACK\n" );
314 end = ( ( char * ) &oack->udp ) + ntohs ( oack->udp.len );
316 /* Only possible error */
319 for ( p = oack->data ; p < end ; ) {
320 if ( strcasecmp ( "blksize", p ) == 0 ) {
322 state->blksize = strtoul ( p, &p, 10 );
324 DBG ( "TFTPCORE: garbage \"%s\" "
325 "after blksize\n", p );
329 DBG ( "TFTPCORE: got blksize %d\n", state->blksize );
330 } else if ( strcasecmp ( "tsize", p ) == 0 ) {
332 state->tsize = strtoul ( p, &p, 10 );
334 DBG ( "TFTPCORE: garbage \"%s\" "
335 "after tsize\n", p );
339 DBG ( "TFTPCORE: got tsize %d\n", state->tsize );
340 } else if ( strcasecmp ( "multicast", p ) == 0 ) {
341 char *e = strchr ( p, ',' );
342 if ( ( ! e ) || ( e >= end ) ) {
343 DBG ( "TFTPCORE: malformed multicast field "
347 /* IP address may be missing, in which case we
348 * should leave state->client.sin_addr
354 rc = inet_aton ( p, &state->client.sin_addr );
357 DBG ( "TFTPCORE: malformed multicast "
358 "IP address \"%s\"\n", p );
363 /* UDP port may also be missing */
365 state->client.sin_port = strtoul ( p, &p, 10 );
367 DBG ( "TFTPCORE: garbage \"%s\" "
368 "after multicast port\n", p );
374 /* "Master Client" must always be present */
375 state->master = strtoul ( p, &p, 10 );
377 DBG ( "TFTPCORE: garbage \"%s\" "
378 "after multicast mc\n", p );
382 DBG ( "TFTPCORE: got multicast %@:%d (%s)\n",
383 state->client.sin_addr.s_addr,
384 state->client.sin_port,
385 ( state->master ? "master" : "not master" ) );
387 DBG ( "TFTPCORE: unknown option \"%s\"\n", p );
388 p += strlen ( p ) + 1; /* skip option name */
389 p += strlen ( p ) + 1; /* skip option value */
394 DBG ( "TFTPCORE: overran options in OACK\n" );
402 * Acknowledge a TFTP packet
404 * @v state TFTP transfer state
405 * @v tftp_state::server::sin_addr TFTP server IP address
406 * @v tftp_state::server::sin_port TFTP server UDP port
407 * @v tftp_state::client::sin_port Client UDP port
408 * @v tftp_state::block Most recently received block number
409 * @ret True Acknowledgement packet was sent
410 * @ret False Acknowledgement packet was not sent
411 * @err other As returned by udp_transmit()
413 * Send a TFTP ACK packet for the most recently received block.
415 * This sends only a single ACK packet; it does not wait for the
418 int tftp_ack_nowait ( struct tftp_state *state ) {
421 DBG ( "TFTPCORE: acknowledging data block %d\n", state->block );
422 ack.opcode = htons ( TFTP_ACK );
423 ack.block = htons ( state->block );
424 return udp_transmit ( state->server.sin_addr.s_addr,
425 state->client.sin_port, state->server.sin_port,
426 sizeof ( ack ), &ack );
430 * Acknowledge a TFTP packet and wait for a response
432 * @v state TFTP transfer state
433 * @v tftp_state::server::sin_addr TFTP server IP address
434 * @v tftp_state::server::sin_port TFTP server UDP port
435 * @v tftp_state::client::sin_port Client UDP port
436 * @v tftp_state::block Most recently received block number
437 * @ret True Received a non-error response
438 * @ret False Received error response / no response
439 * @ret *reply The server's response, if any
440 * @err #PXENV_STATUS_TFTP_READ_TIMEOUT Timed out waiting for a response
441 * @err other As returned by tftp_ack_nowait()
442 * @err other As set by tftp_set_errno()
444 * Send a TFTP ACK packet for the most recently received data block,
445 * and keep transmitting this ACK until we get a response from the
446 * server (e.g. a new data block).
448 * If the response is a TFTP DATA packet, no processing is done.
449 * Specifically, the block number is not checked to ensure that this
450 * is indeed the next data block in the sequence, nor is
451 * tftp_state::block updated with the new block number.
453 * If the response from the server is a TFTP ERROR packet, tftp_open()
454 * will return False and #errno will be set accordingly.
456 int tftp_ack ( struct tftp_state *state, union tftp_any **reply ) {
460 for ( retry = 0 ; retry < MAX_TFTP_RETRIES ; retry++ ) {
461 long timeout = rfc2131_sleep_interval ( TFTP_REXMT, retry );
462 /* ACK the last data block */
463 if ( ! tftp_ack_nowait ( state ) ) {
464 DBG ( "TFTP: could not send ACK: %m\n" );
467 if ( tftp_get ( state, timeout, reply ) ) {
468 /* We got a non-error response */
472 /* We got an error response */
476 DBG ( "TFTP: timed out during read\n" );
477 errno = PXENV_STATUS_TFTP_READ_TIMEOUT;
484 * @v state TFTP transfer state
485 * @v tftp_state::server::sin_addr TFTP server IP address
486 * @v tftp_state::server::sin_port TFTP server UDP port
487 * @v tftp_state::client::sin_port Client UDP port
488 * @v errcode TFTP error code
489 * @v errmsg Descriptive error string, or NULL
490 * @ret True Error packet was sent
491 * @ret False Error packet was not sent
493 * Send a TFTP ERROR packet back to the server to terminate the
496 * If #errmsg is NULL, the current error message string as returned by
497 * strerror(errno) will be used as the error text.
499 int tftp_error ( struct tftp_state *state, int errcode, const char *errmsg ) {
500 struct tftp_error error;
502 DBG ( "TFTPCORE: aborting with error %d (%s)\n", errcode, errmsg );
503 error.opcode = htons ( TFTP_ERROR );
504 error.errcode = htons ( errcode );
505 strncpy ( error.errmsg, errmsg ? errmsg : strerror ( errno ),
506 sizeof ( error.errmsg ) );
507 return udp_transmit ( state->server.sin_addr.s_addr,
508 state->client.sin_port, state->server.sin_port,
509 sizeof ( error ), &error );
513 * Interpret a TFTP error
515 * @v error Pointer to a struct tftp_error
517 * Sets #errno based on the error code in a TFTP ERROR packet.
519 void tftp_set_errno ( struct tftp_error *error ) {
520 static int errmap[] = {
521 [TFTP_ERR_FILE_NOT_FOUND] = PXENV_STATUS_TFTP_FILE_NOT_FOUND,
522 [TFTP_ERR_ACCESS_DENIED] = PXENV_STATUS_TFTP_ACCESS_VIOLATION,
523 [TFTP_ERR_ILLEGAL_OP] = PXENV_STATUS_TFTP_UNKNOWN_OPCODE,
525 unsigned int errcode = ntohs ( error->errcode );
528 if ( errcode < ( sizeof(errmap) / sizeof(errmap[0]) ) )
529 errno = errmap[errcode];
531 errno = PXENV_STATUS_TFTP_ERROR_OPCODE;