Browse Source

Rewritten to use the functions in tftpcore.c.

Works with a non-multicast TFTP server (i.e. the fallback path works
fine).
tags/v0.9.3
Michael Brown 19 years ago
parent
commit
f242f56a73
1 changed files with 166 additions and 445 deletions
  1. 166
    445
      src/proto/tftm.c

+ 166
- 445
src/proto/tftm.c View File

@@ -1,487 +1,208 @@
1
-#if 0
2
-
3
-/**************************************************************************
4
-*
5
-*    proto_tftm.c -- Etherboot Multicast TFTP 
6
-*    Written 2003-2003 by Timothy Legge <tlegge@rogers.com>
7
-*
8
-*    This program is free software; you can redistribute it and/or modify
9
-*    it under the terms of the GNU General Public License as published by
10
-*    the Free Software Foundation; either version 2 of the License, or
11
-*    (at your option) any later version.
12
-*
13
-*    This program is distributed in the hope that it will be useful,
14
-*    but WITHOUT ANY WARRANTY; without even the implied warranty of
15
-*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
-*    GNU General Public License for more details.
17
-*
18
-*    You should have received a copy of the GNU General Public License
19
-*    along with this program; if not, write to the Free Software
20
-*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
-*
22
-*    This code is based on the DOWNLOAD_PROTO_TFTM section of 
23
-*    Etherboot 5.3 core/nic.c and:
24
-*    
25
-*    Anselm Martin Hoffmeister's previous proto_tftm.c multicast work
26
-*    Eric Biederman's proto_slam.c
27
-*
28
-*    $Revision$
29
-*    $Author$
30
-*    $Date$
31
-*
32
-*    REVISION HISTORY:
33
-*    ================
34
-*    09-07-2003	timlegge	Release Version, Capable of Multicast Booting
35
-*    08-30-2003	timlegge	Initial version, Assumes consecutive blocks
36
-*
37
-*    Indent Options: indent -kr -i8
38
-***************************************************************************/
1
+#include "etherboot.h"
2
+#include "proto.h"
3
+#include "errno.h"
4
+#include "tftp.h"
5
+#include "tftpcore.h"
39 6
 
40
-/*
41
- * IMPORTANT
7
+/** @file
42 8
  *
43
- * This file should be rewritten to avoid the use of a bitmap.  Our
44
- * buffer routines can cope with being handed blocks in an arbitrary
45
- * order, duplicate blocks, etc.  This code could be substantially
46
- * simplified by taking advantage of these features.
9
+ * TFTM protocol
47 10
  *
11
+ * TFTM is a protocol defined in RFC2090 as a multicast extension to
12
+ * TFTP.
48 13
  */
49 14
 
50
-#include "etherboot.h"
51
-#include "proto.h"
52
-#include "nic.h"
15
+static inline int tftm_process_opts ( struct tftp_state *state,
16
+				      struct tftp_oack *oack ) {
17
+	struct in_addr old_mcast_addr = state->client.sin_addr;
53 18
 
54
-struct tftm_info {
55
-	struct sockaddr_in server;
56
-	struct sockaddr_in local;
57
-	struct sockaddr_in multicast;
58
-	int sent_nack;
59
-	const char *name;	/* Filename */
60
-};
19
+	if ( ! tftp_process_opts ( state, oack ) )
20
+		return 0;
61 21
 
62
-struct tftm_state {
63
-	unsigned long block_size;
64
-	unsigned long total_bytes;
65
-	unsigned long total_packets;
66
-	char ismaster;
67
-	unsigned long received_packets;
68
-	struct buffer *buffer;
69
-	unsigned char *image;
70
-	unsigned char *bitmap;
71
-	char recvd_oack;
72
-} state;
22
+	if ( old_mcast_addr.s_addr != state->client.sin_addr.s_addr ) {
23
+		if ( old_mcast_addr.s_addr ) {
24
+			DBG ( "TFTM: Leaving multicast group %@\n",
25
+			      old_mcast_addr.s_addr );
26
+			leave_group ( IGMP_SERVER );
27
+		}
28
+		DBG ( "TFTM: Joining multicast group %@\n",
29
+		      state->client.sin_addr.s_addr );
30
+		join_group ( IGMP_SERVER, state->client.sin_addr.s_addr );
31
+	}
73 32
 
74
-#define TFTM_PORT 1758
75
-#define TFTM_MIN_PACKET 1024
33
+	DBG ( "TFTM: I am a %s client\n",
34
+	      ( state->master ? "master" : "slave" ) );
76 35
 
36
+	return 1;
37
+}
77 38
 
78
-static int opt_get_multicast(struct tftp_t *tr, unsigned short *len,
79
-			     unsigned long *filesize, struct tftm_info *info);
80 39
 
81
-static int await_tftm(int ival, void *ptr, unsigned short ptype __unused,
82
-		      struct iphdr *ip, struct udphdr *udp,
83
-		      struct tcphdr *tcp __unused)
84
-{
85
-	struct tftm_info *info = ptr;
40
+static inline int tftm_process_data ( struct tftp_state *state,
41
+				      struct tftp_data *data,
42
+				      struct buffer *buffer ) {
43
+	unsigned int blksize;
44
+	off_t offset;
86 45
 
87
-	/* Check for Unicast data being received */
88
-	if (ip->dest.s_addr == arptable[ARP_CLIENT].ipaddr.s_addr) {
89
-		if (!udp) {
90
-			return 0;
91
-		}
92
-		if (arptable[ARP_CLIENT].ipaddr.s_addr != ip->dest.s_addr)
93
-			return 0;
94
-		if (ntohs(udp->dest) != ival)
95
-			return 0;
46
+	/* Calculate block size and offset within file */
47
+	blksize = ( ntohs ( data->udp.len )
48
+		    + offsetof ( typeof ( *data ), udp )
49
+		    - offsetof ( typeof ( *data ), data ) );
50
+	offset = ( ntohs ( data->block ) - 1 ) * state->blksize;
96 51
 
97
-		return 1;	/* Unicast Data Received */
52
+	/* Check for oversized block */
53
+	if ( blksize > state->blksize ) {
54
+		DBG ( "TFTM: oversized block size %d (max %d)\n",
55
+		      blksize, state->blksize );
56
+		errno = PXENV_STATUS_TFTP_INVALID_PACKET_SIZE;
57
+		return 0;
98 58
 	}
99 59
 
100
-	/* Also check for Multicast data being received */
101
-	if ((ip->dest.s_addr == info->multicast.sin_addr.s_addr) &&
102
-	    (ntohs(udp->dest) == info->multicast.sin_port) &&
103
-	    (nic.packetlen >= ETH_HLEN + sizeof(struct iphdr) +
104
-	     sizeof(struct udphdr))) {
105
-		return 1;	/* Multicast data received */
60
+	/* Place block in the buffer */
61
+	if ( ! fill_buffer ( buffer, data->data, offset, blksize ) ) {
62
+		DBG ( "TFTM: could not place data in buffer: %m\n" );
63
+		return 0;
106 64
 	}
107
-	return 0;
108
-}
109
-
110
-static int proto_tftm(struct tftm_info *info)
111
-{
112
-	int retry = 0;
113
-	static unsigned short iport = 2000;
114
-	unsigned short oport = 0;
115
-	unsigned short len, block = 0, prevblock = 0;
116
-	struct tftp_t *tr;
117
-	struct tftpreq_t tp;
118
-	unsigned long filesize = 0;
119 65
 
120
-	state.image = 0;
121
-	state.bitmap = 0;
66
+	/* If this is the last block, record the filesize (in case the
67
+	 * server didn't supply a tsize option.
68
+	 */
69
+	if ( blksize < state->blksize ) {
70
+		state->tsize = offset + blksize;
71
+	}
122 72
 
123
-	rx_qdrain();
73
+	/* Record the last received block */
74
+	state->block = ntohs ( data->block );
124 75
 
125
-	/* Warning: the following assumes the layout of bootp_t.
126
-	   But that's fixed by the IP, UDP and BOOTP specs. */
76
+	return 1;
77
+}
127 78
 
128
-	/* Send a tftm-request to the server */
129
-	tp.opcode = htons(TFTP_RRQ);	/* Const for "\0x0" "\0x1" =^= ReadReQuest */
130
-	len =
131
-	    sizeof(tp.ip) + sizeof(tp.udp) + sizeof(tp.opcode) +
132
-	    sprintf((char *) tp.u.rrq,
133
-		    "%s%coctet%cmulticast%c%cblksize%c%d%ctsize%c",
134
-		    info->name, 0, 0, 0, 0, 0, TFTM_MIN_PACKET, 0, 0) + 1;
135 79
 
136
-	if (!udp_transmit(info->server.sin_addr.s_addr, ++iport,
137
-			  info->server.sin_port, len, &tp))
138
-		return (0);
80
+static inline int tftm_next ( struct tftp_state *state,
81
+			      union tftp_any **reply,
82
+			      struct buffer *buffer ) {
83
+	long listen_timeout;
139 84
 
140
-	/* loop to listen for packets and to receive the file */
141
-	for (;;) {
142
-		long timeout;
143
-#ifdef	CONGESTED
144
-		timeout =
145
-		    rfc2131_sleep_interval(block ? TFTP_REXMT : TIMEOUT,
146
-					   retry);
147
-#else
148
-		timeout = rfc2131_sleep_interval(TIMEOUT, retry);
149
-#endif
150
-		/* Calls the await_reply function in nic.c which in turn calls
151
-		   await_tftm (1st parameter) as above */
152
-		if (!await_reply(await_tftm, iport, info, timeout)) {
153
-			if (!block && retry++ < MAX_TFTP_RETRIES) {	/* maybe initial request was lost */
154
-				if (!udp_transmit
155
-				    (info->server.sin_addr.s_addr, ++iport,
156
-				     info->server.sin_port, len, &tp))
157
-					return (0);
158
-				continue;
159
-			}
160
-#ifdef	CONGESTED
161
-			if (block && ((retry += TFTP_REXMT) < TFTP_TIMEOUT)) {	/* we resend our last ack */
162
-				DBG("Timed out receiving file");
163
-				len =
164
-				    sizeof(tp.ip) + sizeof(tp.udp) +
165
-				    sizeof(tp.opcode) +
166
-				    sprintf((char *) tp.u.rrq,
167
-					    "%s%coctet%cmulticast%c%cblksize%c%d%ctsize%c",
168
-					    info->name, 0, 0, 0, 0, 0,
169
-					    TFTM_MIN_PACKET, 0, 0) + 1;
85
+	listen_timeout = rfc2131_sleep_interval ( TIMEOUT, MAX_TFTP_RETRIES );
170 86
 
171
-				udp_transmit
172
-					(info->server.sin_addr.s_addr,
173
-					 ++iport, info->server.sin_port,
174
-					 len, &tp);
175
-					continue;
176
-			}
177
-#endif
178
-			break;	/* timeout */
87
+	/* If we are not the master client, just listen for the next
88
+	 * packet
89
+	 */
90
+	if ( ! state->master ) {
91
+		if ( tftp_get ( state, listen_timeout, reply ) ) {
92
+			/* Heard a non-error packet */
93
+			return 1;
179 94
 		}
180
-
181
-		tr = (struct tftp_t *) &nic.packet[ETH_HLEN];
182
-
183
-		if (tr->opcode == ntohs(TFTP_ERROR)) {
184
-			printf("TFTP error %d (%s)\n",
185
-			       ntohs(tr->u.err.errcode), tr->u.err.errmsg);
186
-			break;
95
+		if ( *reply ) {
96
+			/* Received an error packet */
97
+			return 0;
187 98
 		}
99
+		/* Didn't hear anything; try prodding the server */
100
+		state->master = 1;
101
+	}
102
+	/* We are the master client; trigger the next packet
103
+	 * that we want
104
+	 */
105
+	state->block = buffer->fill / state->blksize;
106
+	return tftp_ack ( state, reply );
107
+}
188 108
 
189
-		if (tr->opcode == ntohs(TFTP_OACK)) {
190
-			int i =
191
-			    opt_get_multicast(tr, &len, &filesize, info);
192
-
193
-			if (i == 0 || (i != 7 && !state.recvd_oack)) {	/* Multicast unsupported */
194
-				/* Transmit an error message to the server to end the transmission */
195
-				printf
196
-				    ("TFTM-Server doesn't understand options [blksize tsize multicast]\n");
197
-				tp.opcode = htons(TFTP_ERROR);
198
-				tp.u.err.errcode = 8;
199
-				/*
200
-				 *      Warning: the following assumes the layout of bootp_t.
201
-				 *      But that's fixed by the IP, UDP and BOOTP specs.
202
-				 */
203
-				len =
204
-				    sizeof(tp.ip) + sizeof(tp.udp) +
205
-				    sizeof(tp.opcode) +
206
-				    sizeof(tp.u.err.errcode) +
207
-				    /*
208
-				     *      Normally bad form to omit the format string, but in this case
209
-				     *      the string we are copying from is fixed. sprintf is just being
210
-				     *      used as a strcpy and strlen.
211
-				     */
212
-				    sprintf((char *) tp.u.err.errmsg,
213
-					    "RFC2090 error") + 1;
214
-				udp_transmit(info->server.sin_addr.s_addr,
215
-					     iport, ntohs(tr->udp.src),
216
-					     len, &tp);
217
-				block = tp.u.ack.block = 0;	/* this ensures, that */
218
-				/* the packet does not get */
219
-				/* processed as data! */
220
-				return (0);
221
-			} else {
222
-				unsigned long bitmap_len;
223
-				/* */
224
-				if (!state.recvd_oack) {
225
-
226
-					state.total_packets =
227
-					    1 + (filesize -
228
-						 (filesize %
229
-						  state.block_size)) /
230
-					    state.block_size;
231
-					bitmap_len =
232
-					    (state.total_packets + 7) / 8;
233
-					if (!state.image) {
234
-						state.image = phys_to_virt ( state.buffer->start );
235
-						state.bitmap = state.image + filesize;
236
-						/* We don't yet use the buffer routines; fake it */
237
-						state.buffer->fill = filesize;
238
-
239
-						memset(state.bitmap, 0,
240
-						       bitmap_len);
241
-					}
242
-					/* If I'm running over multicast join the multicast group */
243
-					join_group(IGMP_SERVER,
244
-					      info->multicast.sin_addr.s_addr);
245
-				}
246
-				state.recvd_oack = 1;
247
-			}
248
-
249
-
250
-
251
-		} else if (tr->opcode == htons(TFTP_DATA)) {
252
-			unsigned long data_len;
253
-			unsigned char *data;
254
-			struct udphdr *udp;
255
-			udp =
256
-			    (struct udphdr *) &nic.packet[ETH_HLEN +
257
-							  sizeof(struct
258
-								 iphdr)];
259
-			len =
260
-			    ntohs(tr->udp.len) - sizeof(struct udphdr) - 4;
261
-			data =
262
-			    nic.packet + ETH_HLEN + sizeof(struct iphdr) +
263
-			    sizeof(struct udphdr) + 4;
264
-
265
-			if (len > TFTM_MIN_PACKET)	/* shouldn't happen */
266
-				continue;	/* ignore it */
267
-
268
-			block = ntohs(tp.u.ack.block = tr->u.data.block);
269
-
270
-			if (block > state.total_packets) {
271
-				printf("ALERT: Invalid packet number\n");
272
-				continue;
273
-			}
274
-
275
-			/* Compute the expected data length */
276
-			if (block != state.total_packets) {
277
-				data_len = state.block_size;
278
-			} else {
279
-				data_len = filesize % state.block_size;
280
-			}
281
-			/* If the packet size is wrong drop the packet and then continue */
282
-			if (ntohs(udp->len) !=
283
-			    (data_len + (data - (unsigned char *) udp))) {
284
-				printf
285
-				    ("ALERT: udp packet is not the correct size: %d\n",
286
-				     block);
287
-				continue;
288
-			}
289
-			if (nic.packetlen < data_len + (data - nic.packet)) {
290
-				printf
291
-				    ("ALERT: Ethernet packet shorter than data_len: %d\n",
292
-				     block);
293
-				continue;
294
-			}
295
-
296
-			if (data_len > state.block_size) {
297
-				data_len = state.block_size;
298
-			}
299
-			if (((state.
300
-			      bitmap[block >> 3] >> (block & 7)) & 1) ==
301
-			    0) {
302
-				/* Non duplicate packet */
303
-				state.bitmap[block >> 3] |=
304
-				    (1 << (block & 7));
305
-				memcpy(state.image +
306
-				       ((block - 1) * state.block_size),
307
-				       data, data_len);
308
-				state.received_packets++;
309
-			} else {
109
+/**
110
+ * Download a file via TFTM
111
+ *
112
+ * @v server				TFTP server
113
+ * @v file				File name
114
+ * @v buffer				Buffer into which to load file
115
+ * @ret True				File was downloaded successfully
116
+ * @ret False				File was not downloaded successfully
117
+ * @err #PXENV_STATUS_TFTP_UNKNOWN_OPCODE Unknown type of TFTP block received
118
+ * @err other				As returned by tftp_open()
119
+ * @err other				As returned by tftp_process_opts()
120
+ * @err other				As returned by tftp_ack()
121
+ * @err other				As returned by tftp_process_data()
122
+ *
123
+ * Download a file from a TFTP server into the specified buffer using
124
+ * the TFTM protocol.
125
+ */
126
+static int tftm ( char *url __unused, struct sockaddr_in *server, char *file,
127
+		  struct buffer *buffer ) {
128
+	struct tftp_state state;
129
+	union tftp_any *reply;
130
+	int rc = 0;
131
+
132
+	/* Initialise TFTP state */
133
+	memset ( &state, 0, sizeof ( state ) );
134
+	state.server = *server;
135
+
136
+	/* Start as the master.  This means that if the TFTP server
137
+	 * doesn't actually support multicast, we'll still ACK the
138
+	 * packets and it should all proceed as for a normal TFTP
139
+	 * connection.
140
+	 */
141
+	state.master = 1;
142
+	
143
+	/* Open the file */
144
+	if ( ! tftp_open ( &state, file, &reply, 1 ) ) {
145
+		DBG ( "TFTM: could not open %@:%d/%s : %m\n",
146
+		      server->sin_addr.s_addr, server->sin_port, file );
147
+		return 0;
148
+	}
310 149
 
311
-/*				printf("<DUP>\n"); */
150
+	/* Fetch file, a block at a time */
151
+	while ( 1 ) {
152
+		twiddle();
153
+		/* Process the current packet */
154
+		switch ( ntohs ( reply->common.opcode ) ) {
155
+		case TFTP_OACK:
156
+			/* Options can be received at any time */
157
+			if ( ! tftm_process_opts ( &state, &reply->oack ) ) {
158
+				DBG ( "TFTM: failed to process OACK: %m\n" );
159
+				tftp_error ( &state, TFTP_ERR_BAD_OPTS, NULL );
160
+				goto out;
312 161
 			}
313
-		}
314
-
315
-		else {		/* neither TFTP_OACK, TFTP_DATA nor TFTP_ERROR */
316 162
 			break;
317
-		}
318
-
319
-		if (state.received_packets <= state.total_packets) {
320
-			unsigned long b;
321
-			unsigned long len;
322
-			unsigned long max;
323
-			int value;
324
-			int last;
325
-
326
-			/* Compute the last bit and store an inverted trailer */
327
-			max = state.total_packets + 1;
328
-			value =
329
-			    ((state.
330
-			      bitmap[(max - 1) >> 3] >> ((max -
331
-							  1) & 7)) & 1);
332
-			value = !value;
333
-			state.bitmap[max >> 3] &= ~(1 << (max & 7));
334
-			state.bitmap[max >> 3] |= value << (max & 7);
335
-
336
-			len = 0;
337
-			last = 0;	/* Start with the received packets */
338
-			for (b = 1; b <= max; b++) {
339
-				value =
340
-				    (state.bitmap[b >> 3] >> (b & 7)) & 1;
341
-
342
-				if (value == 0) {
343
-					tp.u.ack.block = htons(b - 1);	/* Acknowledge the previous block */
344
-					break;
345
-				}
163
+		case TFTP_DATA:
164
+			if ( ! tftm_process_data ( &state, &reply->data,
165
+						   buffer ) ) {
166
+				DBG ( "TFTM: failed to process DATA: %m\n" );
167
+				tftp_error ( &state, TFTP_ERR_ILLEGAL_OP,
168
+					     NULL );
169
+				goto out;
346 170
 			}
347
-		}
348
-		if (state.ismaster) {
349
-			tp.opcode = htons(TFTP_ACK);
350
-			oport = ntohs(tr->udp.src);
351
-			udp_transmit(info->server.sin_addr.s_addr, iport,
352
-				     oport, TFTP_MIN_PACKET, &tp); /* ack */
353
-		}
354
-		if (state.received_packets == state.total_packets) {
355
-			/* If the client is finished and not the master,
356
-			 * ack the last packet */
357
-			if (!state.ismaster) {
358
-				tp.opcode = htons(TFTP_ACK);
359
-				/* Ack Last packet to end xfer */
360
-				tp.u.ack.block = htons(state.total_packets);
361
-				oport = ntohs(tr->udp.src);
362
-				udp_transmit(info->server.sin_addr.s_addr,
363
-					     iport, oport,
364
-					     TFTP_MIN_PACKET, &tp); /* ack */
365
-			}
366
-			/* We are done get out */
367 171
 			break;
172
+		default:
173
+			DBG ( "TFTM: unexpected packet type %d\n",
174
+			      ntohs ( reply->common.opcode ) );
175
+			errno = PXENV_STATUS_TFTP_UNKNOWN_OPCODE;
176
+			tftp_error ( &state, TFTP_ERR_ILLEGAL_OP, NULL );
177
+			goto out;
368 178
 		}
369
-
370
-		if ((unsigned short) (block - prevblock) != 1) {
371
-			/* Retransmission or OACK, don't process via callback
372
-			 * and don't change the value of prevblock.  */
373
-			continue;
179
+		/* If we know the filesize, and we have all the data, stop */
180
+		if ( state.tsize && ( buffer->fill == state.tsize ) )
181
+			break;
182
+		/* Fetch the next packet */
183
+		if ( ! tftm_next ( &state, &reply, buffer ) ) {
184
+			DBG ( "TFTM: could not get next block: %m\n" );
185
+			if ( ! reply ) {
186
+				tftp_error ( &state, TFTP_ERR_ILLEGAL_OP,
187
+					     NULL );
188
+			}
189
+			goto out;
374 190
 		}
375
-
376
-		prevblock = block;
377
-		retry = 0;	/* It's the right place to zero the timer? */
378
-
379
-	}
380
-	/* Leave the multicast group */
381
-	leave_group(IGMP_SERVER);
382
-	return 1;
383
-}
384
-
385
-static int url_tftm ( char *url __unused, struct sockaddr_in *server,
386
-		      char *file, struct buffer *buffer ) {
387
-
388
-	int ret;
389
-	struct tftm_info info;
390
-
391
-	/* Set the defaults */
392
-	info.server = *server;
393
-	info.local.sin_addr.s_addr = arptable[ARP_CLIENT].ipaddr.s_addr;
394
-	info.local.sin_port = TFTM_PORT; /* Does not matter. */
395
-	info.multicast = info.local;
396
-	state.ismaster = 0;
397
-	info.name = file;
398
-
399
-	state.block_size = 0;
400
-	state.total_bytes = 0;
401
-	state.total_packets = 0;
402
-	state.received_packets = 0;
403
-	state.buffer = buffer;
404
-	state.image = 0;
405
-	state.bitmap = 0;
406
-	state.recvd_oack = 0;
407
-
408
-	if (file[0] != '/') {
409
-		printf("Bad tftm-URI: [%s]\n", file);
410
-		return 0;
411 191
 	}
412 192
 
413
-	ret = proto_tftm(&info);
414
-
415
-	return ret;
416
-}
417
-
418
-/******************************
419
-* Parse the multicast options
420
-*******************************/
421
-static int opt_get_multicast(struct tftp_t *tr, unsigned short *len,
422
-			     unsigned long *filesize, struct tftm_info *info)
423
-{
424
-	const char *p = tr->u.oack.data, *e = 0;
425
-	int i = 0;
426
-	*len = ntohs(tr->udp.len) - sizeof(struct udphdr) - 2;
427
-	if (*len > TFTM_MIN_PACKET)
428
-		return -1;
429
-	e = p + *len;
193
+	/* ACK the final packet, as a courtesy to the server */
194
+	tftp_ack_nowait ( &state );
430 195
 
431
-	while (*p != '\0' && p < e) {
432
-		if (!strcasecmp("tsize", p)) {
433
-			p += 6;
434
-			if ((*filesize = strtoul(p, &p, 10)) > 0)
435
-				i |= 4;
436
-			DBG("\n");
437
-			DBG("tsize=%d\n", *filesize);
438
-			while (p < e && *p)
439
-				p++;
440
-			if (p < e)
441
-				p++;
442
-		} else if (!strcasecmp("blksize", p)) {
443
-			i |= 2;
444
-			p += 8;
445
-			state.block_size = strtoul(p, &p, 10);
446
-			if (state.block_size != TFTM_MIN_PACKET) {
447
-				printf
448
-				    ("TFTM-Server rejected required transfer blocksize %d\n",
449
-				     TFTM_MIN_PACKET);
450
-				return 0;
451
-			}
452
-			DBG("blksize=%d\n", state.block_size);
453
-			while (p < e && *p)
454
-				p++;
455
-			if (p < e)
456
-				p++;
457
-		} else if (!strncmp(p, "multicast", 10)) {
458
-			i |= 1;
459
-			p += 10;
460
-			DBG("multicast options: %s\n", p);
461
-			p += 1 + inet_aton(p, &info->multicast.sin_addr);
462
-			DBG("multicast ip = %@\n", info->multicast_ip);
463
-			info->multicast.sin_port = strtoul(p, &p, 10);
464
-			++p;
465
-			DBG("multicast port = %d\n",
466
-			    info->multicast.sin_port);
467
-			state.ismaster = (*p == '1' ? 1 : 0);
468
-			DBG("multicast ismaster = %d\n",
469
-			       state.ismaster);
470
-			while (p < e && *p)
471
-				p++;
472
-			if (p < e)
473
-				p++;
474
-		}
196
+	rc = 1;
197
+ out:
198
+	if ( state.client.sin_addr.s_addr ) {
199
+		leave_group ( IGMP_SERVER );
475 200
 	}
476
-	if (p > e)
477
-		return 0;
478
-	return i;
201
+	return rc;
479 202
 }
480 203
 
481 204
 static struct protocol tftm_protocol __protocol = {
482 205
 	.name = "x-tftm",
483
-	.default_port = TFTM_PORT,
484
-	.load = url_tftm,
206
+	.default_port = TFTP_PORT,
207
+	.load = tftm,
485 208
 };
486
-
487
-#endif

Loading…
Cancel
Save