|
@@ -125,6 +125,7 @@ int tftp_get ( struct tftp_state *state, long timeout,
|
125
|
125
|
* @v tftp_state::client::sin_port Client UDP port, or 0
|
126
|
126
|
* @v tftp_state::blksize Requested blksize, or 0
|
127
|
127
|
* @v filename File name
|
|
128
|
+ * @v multicast Enable/disable rfc2090 multicast TFTP
|
128
|
129
|
* @ret True Received a non-error response
|
129
|
130
|
* @ret False Received error response / no response
|
130
|
131
|
* @ret tftp_state::server::sin_port TFTP server UDP port
|
|
@@ -182,9 +183,10 @@ int tftp_get ( struct tftp_state *state, long timeout,
|
182
|
183
|
* the server's response originated. This may or may not be the port
|
183
|
184
|
* to which the open request was sent.
|
184
|
185
|
*
|
185
|
|
- * The options "blksize", "tsize" and "multicast" will always be
|
186
|
|
- * appended to a TFTP open request. Servers that do not understand
|
187
|
|
- * any of these options should simply ignore them.
|
|
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.
|
188
|
190
|
*
|
189
|
191
|
* tftp_open() will not automatically join or leave multicast groups;
|
190
|
192
|
* the caller is responsible for calling join_group() and
|
|
@@ -194,10 +196,11 @@ int tftp_get ( struct tftp_state *state, long timeout,
|
194
|
196
|
* will return False and #errno will be set accordingly.
|
195
|
197
|
*/
|
196
|
198
|
int tftp_open ( struct tftp_state *state, const char *filename,
|
197
|
|
- union tftp_any **reply ) {
|
|
199
|
+ union tftp_any **reply, int multicast ) {
|
198
|
200
|
static unsigned short lport = 2000; /* local port */
|
199
|
201
|
int fixed_lport;
|
200
|
202
|
struct tftp_rrq rrq;
|
|
203
|
+ char *p;
|
201
|
204
|
unsigned int rrqlen;
|
202
|
205
|
int retry;
|
203
|
206
|
|
|
@@ -217,11 +220,13 @@ int tftp_open ( struct tftp_state *state, const char *filename,
|
217
|
220
|
|
218
|
221
|
/* Set up RRQ */
|
219
|
222
|
rrq.opcode = htons ( TFTP_RRQ );
|
220
|
|
- rrqlen = ( offsetof ( typeof ( rrq ), data ) +
|
221
|
|
- sprintf ( rrq.data,
|
222
|
|
- "%s%coctet%cblksize%c%d%ctsize%c0%cmulticast%c",
|
223
|
|
- filename, 0, 0, 0, state->blksize, 0, 0, 0, 0 )
|
224
|
|
- + 1 );
|
|
223
|
+ p = rrq.data;
|
|
224
|
+ p += sprintf ( p, "%s%coctet%cblksize%c%d%ctsize%c0",
|
|
225
|
+ filename, 0, 0, 0, state->blksize, 0, 0 ) + 1;
|
|
226
|
+ if ( multicast ) {
|
|
227
|
+ p += sprintf ( p, "multicast%c", 0 ) + 1;
|
|
228
|
+ }
|
|
229
|
+ rrqlen = ( p - ( char * ) &rrq );
|
225
|
230
|
|
226
|
231
|
/* Set negotiated blksize to default value */
|
227
|
232
|
state->blksize = TFTP_DEFAULT_BLKSIZE;
|
|
@@ -257,7 +262,7 @@ int tftp_open ( struct tftp_state *state, const char *filename,
|
257
|
262
|
state->server.sin_port );
|
258
|
263
|
return 1;
|
259
|
264
|
}
|
260
|
|
- if ( reply ) {
|
|
265
|
+ if ( *reply ) {
|
261
|
266
|
/* We got an error response; abort */
|
262
|
267
|
return 0;
|
263
|
268
|
}
|
|
@@ -463,7 +468,7 @@ int tftp_ack ( struct tftp_state *state, union tftp_any **reply ) {
|
463
|
468
|
/* We got a non-error response */
|
464
|
469
|
return 1;
|
465
|
470
|
}
|
466
|
|
- if ( reply ) {
|
|
471
|
+ if ( *reply ) {
|
467
|
472
|
/* We got an error response */
|
468
|
473
|
return 0;
|
469
|
474
|
}
|