Переглянути джерело

In multicast operation, the client still has a unicast local port.

tags/v0.9.3
Michael Brown 19 роки тому
джерело
коміт
7d8adc25bc
3 змінених файлів з 103 додано та 95 видалено
  1. 9
    10
      src/include/tftp.h
  2. 5
    5
      src/proto/tftm.c
  3. 89
    80
      src/proto/tftpcore.c

+ 9
- 10
src/include/tftp.h Переглянути файл

@@ -100,19 +100,18 @@ struct tftp_state {
100 100
 	 * will be sent, and to which ACK packets should be sent.
101 101
 	 */
102 102
 	struct sockaddr_in server;
103
-	/** TFTP client address
103
+	/** TFTP client port
104 104
 	 *
105
-	 * The IP address, if any, is the multicast address to which
106
-	 * data packets will be sent.  The client will always send
107
-	 * packets from its own IP address.
105
+	 * This is the UDP port from which the open request will be
106
+	 * sent, and to which any unicast data packets will be sent.
107
+	 */
108
+	in_port_t lport;
109
+	/** TFTP multicast address
108 110
 	 *
109
-	 * The UDP port is the port from which the open request will
110
-	 * be sent, and to which data packets will be sent.  (Due to
111
-	 * the "design" of the MTFTP protocol, the master client will
112
-	 * receive its first data packet as unicast, and subsequent
113
-	 * packets as multicast.)
111
+	 * This is the IP address and UDP port to which multicast data
112
+	 * packets, if any, will be sent.
114 113
 	 */
115
-	struct sockaddr_in client;
114
+	struct sockaddr_in multicast;
116 115
 	/** Master client
117 116
 	 *
118 117
 	 * This will be true if the client is the master client for a

+ 5
- 5
src/proto/tftm.c Переглянути файл

@@ -14,20 +14,20 @@
14 14
 
15 15
 static inline int tftm_process_opts ( struct tftp_state *state,
16 16
 				      struct tftp_oack *oack ) {
17
-	struct in_addr old_mcast_addr = state->client.sin_addr;
17
+	struct in_addr old_mcast_addr = state->multicast.sin_addr;
18 18
 
19 19
 	if ( ! tftp_process_opts ( state, oack ) )
20 20
 		return 0;
21 21
 
22
-	if ( old_mcast_addr.s_addr != state->client.sin_addr.s_addr ) {
22
+	if ( old_mcast_addr.s_addr != state->multicast.sin_addr.s_addr ) {
23 23
 		if ( old_mcast_addr.s_addr ) {
24 24
 			DBG ( "TFTM: Leaving multicast group %@\n",
25 25
 			      old_mcast_addr.s_addr );
26 26
 			leave_group ( IGMP_SERVER );
27 27
 		}
28 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 );
29
+		      state->multicast.sin_addr.s_addr );
30
+		join_group ( IGMP_SERVER, state->multicast.sin_addr.s_addr );
31 31
 	}
32 32
 
33 33
 	DBG ( "TFTM: I am a %s client\n",
@@ -195,7 +195,7 @@ static int tftm ( char *url __unused, struct sockaddr_in *server, char *file,
195 195
 
196 196
 	rc = 1;
197 197
  out:
198
-	if ( state.client.sin_addr.s_addr ) {
198
+	if ( state.multicast.sin_addr.s_addr ) {
199 199
 		leave_group ( IGMP_SERVER );
200 200
 	}
201 201
 	return rc;

+ 89
- 80
src/proto/tftpcore.c Переглянути файл

@@ -9,19 +9,20 @@
9 9
 /**
10 10
  * await_reply() filter for TFTP packets
11 11
  *
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
16
- * @v ip			IP header
17
- * @v udp			UDP header
18
- * @ret True			This is our TFTP packet
19
- * @ret False			This is not one of our 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::lport			Client UDP port
15
+ * @v tftp_state::multicast::sin_addr	Multicast IP address, or 0.0.0.0
16
+ * @v tftp_state::multicast::sin_port	Multicast UDP port, or 0
17
+ * @v ip				IP header
18
+ * @v udp				UDP header
19
+ * @ret True				This is our TFTP packet
20
+ * @ret False				This is not one of our TFTP packets
20 21
  *
21 22
  * Wait for a TFTP packet that is part of the current connection
22 23
  * (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
24
- * listening address).
24
+ * and is addressed either to our IP address and UDP port, or to our
25
+ * multicast listening address and UDP port).
25 26
  *
26 27
  * Use await_tftp() in code such as
27 28
  *
@@ -49,39 +50,42 @@ static int await_tftp ( int ival __unused, void *ptr,
49 50
 		       ip->src.s_addr, state->server.sin_addr.s_addr );
50 51
 		return 0;
51 52
 	}
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 );
56
-		return 0;
53
+	/* Packet may be addressed to our IP address and unicast UDP
54
+	 * port
55
+	 */
56
+	if ( ( ip->dest.s_addr == arptable[ARP_CLIENT].ipaddr.s_addr ) &&
57
+	     ( ntohs ( udp->dest ) == state->lport ) ) {
58
+		return 1;
57 59
 	}
58
-	/* Packet must be addressed to us, or to our multicast
59
-	 * listening address (if we have one).
60
+	/* Packet may be addressed to our multicast IP address and UDP
61
+	 * port, if we have one
60 62
 	 */
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 );
67
-		return 0;
63
+	if ( ( state->multicast.sin_addr.s_addr ) && 
64
+	     ( ip->dest.s_addr == state->multicast.sin_addr.s_addr ) &&
65
+	     ( ntohs ( udp->dest ) == state->multicast.sin_port ) ) {
66
+		return 1;
68 67
 	}
69
-	return 1;
68
+	DBG2 ( "TFTPCORE: to %@:%d, not to %@:%d (or %@:%d)\n",
69
+	       ip->dest.s_addr, ntohs ( udp->dest ),
70
+	       arptable[ARP_CLIENT].ipaddr.s_addr, state->lport,
71
+	       state->multicast.sin_addr.s_addr, state->multicast.sin_port );
72
+	return 0;
70 73
 }
71 74
 
72 75
 /**
73 76
  * Retrieve a TFTP packet
74 77
  *
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()
78
+ * @v state				TFTP transfer state
79
+ * @v tftp_state::server::sin_addr	TFTP server IP address
80
+ * @v tftp_state::lport			Client UDP port
81
+ * @v tftp_state::multicast::sin_addr	Multicast IP address, or 0.0.0.0
82
+ * @v tftp_state::multicast::sin_port	Multicast UDP port, or 0
83
+ * @v timeout				Time to wait for a response
84
+ * @ret True				Received a non-error response
85
+ * @ret False				Received error response / no response
86
+ * @ret *reply				The server's response, if any
87
+ * @err #PXENV_STATUS_TFTP_READ_TIMEOUT	No response received in time
88
+ * @err other				As set by tftp_set_errno()
85 89
  *
86 90
  * Retrieve the next packet sent by the TFTP server, if any is sent
87 91
  * within the specified timeout period.  The packet is returned via
@@ -121,15 +125,16 @@ int tftp_get ( struct tftp_state *state, long timeout,
121 125
  * @v state				TFTP transfer state
122 126
  * @v tftp_state::server::sin_addr	TFTP server IP address
123 127
  * @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
128
+ * @v tftp_state::lport			Client UDP port, or 0
129
+ * @v tftp_state::multicast::sin_addr	Multicast IP address, or 0.0.0.0
130
+ * @v tftp_state::multicast::sin_port	Multicast UDP port, or 0
126 131
  * @v tftp_state::blksize		Requested blksize, or 0
127 132
  * @v filename				File name
128 133
  * @v multicast				Enable/disable rfc2090 multicast TFTP
129 134
  * @ret True				Received a non-error response
130 135
  * @ret False				Received error response / no response
131 136
  * @ret tftp_state::server::sin_port	TFTP server UDP port
132
- * @ret tftp_state::client::sin_port	Client UDP port
137
+ * @ret tftp_state::lport		Client UDP port
133 138
  * @ret tftp_state::blksize		Always #TFTP_DEFAULT_BLKSIZE
134 139
  * @ret *reply				The server's response, if any
135 140
  * @err #PXENV_STATUS_TFTP_OPEN_TIMEOUT	TFTP open timed out
@@ -144,32 +149,35 @@ int tftp_get ( struct tftp_state *state, long timeout,
144 149
  * If tftp_state::server::sin_port is 0, the standard TFTP server port
145 150
  * (#TFTP_PORT) will be used.
146 151
  *
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.
149
- *
150
- * If tftp_state::client::sin_port is 0, the standard mechanism of
152
+ * If tftp_state::lport is 0, the standard mechanism of
151 153
  * using a new, unique port number for each TFTP request will be used.
152 154
  * 
155
+ * If tftp_state::multicast::sin_addr is not 0.0.0.0, it (and
156
+ * tftp_state::multicast::sin_port) will be used as a multicast
157
+ * listening address for replies from the TFTP server.
158
+ *
153 159
  * For the various different types of TFTP server, you should treat
154
- * tftp_state::client as follows:
155
- *
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
159
- *     port.
160
- *
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.)
167
- *
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
172
- *     these values.
160
+ * tftp_state::lport and tftp_state::multicast as follows:
161
+ *
162
+ *   - Standard TFTP server: set tftp_state::lport to 0,
163
+ *     tftp_state::multicast::sin_addr to 0.0.0.0 and
164
+ *     tftp_state::multicast::sin_port to 0.  tftp_open() will set
165
+ *     tftp_state::lport to the assigned local UDP port.
166
+ *
167
+ *   - TFTM server: set tftp_state::lport to 0,
168
+ *     tftp_state::multicast::sin_addr to 0.0.0.0 and
169
+ *     tftp_state::multicast::sin_port to 0.  tftp_open() will set
170
+ *     tftp_state::lport to the assigned local UDP port.  (Your call
171
+ *     to tftp_process_opts() will then overwrite both
172
+ *     tftp_state::multicast::sin_addr and
173
+ *     tftp_state::multicast::sin_port with the values specified in
174
+ *     the OACK packet.)
175
+ *
176
+ *   - MTFTP server: set tftp_state::multicast::sin_addr to the
177
+ *     multicast address and both tftp_state::lport and
178
+ *     tftp_state::multicast::sin_port to the multicast port (both of
179
+ *     which must be previously known, e.g. provided by a DHCP
180
+ *     server).  tftp_open() will not alter these values.
173 181
  *
174 182
  * If tftp_state::blksize is 0, the maximum blocksize
175 183
  * (#TFTP_MAX_BLKSIZE) will be requested.
@@ -216,7 +224,7 @@ int tftp_open ( struct tftp_state *state, const char *filename,
216 224
 		state->server.sin_port = TFTP_PORT;
217 225
 
218 226
 	/* Determine whether or not to use lport */
219
-	fixed_lport = state->client.sin_port;
227
+	fixed_lport = state->lport;
220 228
 
221 229
 	/* Set up RRQ */
222 230
 	rrq.opcode = htons ( TFTP_RRQ );
@@ -240,15 +248,14 @@ int tftp_open ( struct tftp_state *state, const char *filename,
240 248
 
241 249
 		/* Set client UDP port, if not already fixed */
242 250
 		if ( ! fixed_lport )
243
-			state->client.sin_port = ++lport;
251
+			state->lport = ++lport;
244 252
 		
245 253
 		/* Send the RRQ */
246 254
 		DBG ( "TFTPCORE: requesting %@:%d/%s from port %d\n",
247 255
 		      state->server.sin_addr.s_addr, state->server.sin_port,
248
-		      rrq.data, state->client.sin_port );
256
+		      rrq.data, state->lport );
249 257
 		if ( ! udp_transmit ( state->server.sin_addr.s_addr,
250
-				      state->client.sin_port,
251
-				      state->server.sin_port,
258
+				      state->lport, state->server.sin_port,
252 259
 				      rrqlen, &rrq ) )
253 260
 			return 0;
254 261
 		
@@ -282,8 +289,8 @@ int tftp_open ( struct tftp_state *state, const char *filename,
282 289
  * @ret False				Options were not processed successfully
283 290
  * @ret tftp_state::blksize		Negotiated blksize
284 291
  * @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
292
+ * @ret tftp_state::multicast::sin_addr	Multicast IP address, or 0.0.0.0
293
+ * @ret tftp_state::multicast::sin_port	Multicast UDP port, or 0
287 294
  * @ret tftp_state::master		Client is master
288 295
  * @err EINVAL				An invalid option value was encountered
289 296
  *
@@ -338,6 +345,7 @@ int tftp_process_opts ( struct tftp_state *state, struct tftp_oack *oack ) {
338 345
 			p++;
339 346
 			DBG ( "TFTPCORE: got tsize %d\n", state->tsize );
340 347
 		} else if ( strcasecmp ( "multicast", p ) == 0 ) {
348
+			p += 10;
341 349
 			char *e = strchr ( p, ',' );
342 350
 			if ( ( ! e ) || ( e >= end ) ) {
343 351
 				DBG ( "TFTPCORE: malformed multicast field "
@@ -345,13 +353,14 @@ int tftp_process_opts ( struct tftp_state *state, struct tftp_oack *oack ) {
345 353
 				return 0;
346 354
 			}
347 355
 			/* IP address may be missing, in which case we
348
-			 * should leave state->client.sin_addr
356
+			 * should leave state->multicast.sin_addr
349 357
 			 * unaltered.
350 358
 			 */
351 359
 			if ( e != p ) {
352 360
 				int rc;
353 361
 				*e = '\0';
354
-				rc = inet_aton ( p, &state->client.sin_addr );
362
+				rc = inet_aton ( p,
363
+						 &state->multicast.sin_addr );
355 364
 				*e = ',';
356 365
 				if ( ! rc ) {
357 366
 					DBG ( "TFTPCORE: malformed multicast "
@@ -362,15 +371,15 @@ int tftp_process_opts ( struct tftp_state *state, struct tftp_oack *oack ) {
362 371
 			p = e + 1;
363 372
 			/* UDP port may also be missing */
364 373
 			if ( *p != ',' ) {
365
-				state->client.sin_port = strtoul ( p, &p, 10 );
374
+				state->multicast.sin_port
375
+					= strtoul ( p, &p, 10 );
366 376
 				if ( *p != ',' ) {
367 377
 					DBG ( "TFTPCORE: garbage \"%s\" "
368 378
 					      "after multicast port\n", p );
369 379
 					return 0;
370 380
 				}
371
-			} else {
372
-				p++;
373 381
 			}
382
+			p++;
374 383
 			/* "Master Client" must always be present */
375 384
 			state->master = strtoul ( p, &p, 10 );
376 385
 			if ( *p ) {
@@ -380,8 +389,8 @@ int tftp_process_opts ( struct tftp_state *state, struct tftp_oack *oack ) {
380 389
 			}
381 390
 			p++;
382 391
 			DBG ( "TFTPCORE: got multicast %@:%d (%s)\n",
383
-			      state->client.sin_addr.s_addr,
384
-			      state->client.sin_port,
392
+			      state->multicast.sin_addr.s_addr,
393
+			      state->multicast.sin_port,
385 394
 			      ( state->master ? "master" : "not master" ) );
386 395
 		} else {
387 396
 			DBG ( "TFTPCORE: unknown option \"%s\"\n", p );
@@ -404,7 +413,7 @@ int tftp_process_opts ( struct tftp_state *state, struct tftp_oack *oack ) {
404 413
  * @v state				TFTP transfer state
405 414
  * @v tftp_state::server::sin_addr	TFTP server IP address
406 415
  * @v tftp_state::server::sin_port	TFTP server UDP port
407
- * @v tftp_state::client::sin_port	Client UDP port
416
+ * @v tftp_state::lport			Client UDP port
408 417
  * @v tftp_state::block			Most recently received block number
409 418
  * @ret True				Acknowledgement packet was sent
410 419
  * @ret False				Acknowledgement packet was not sent
@@ -422,7 +431,7 @@ int tftp_ack_nowait ( struct tftp_state *state ) {
422 431
 	ack.opcode = htons ( TFTP_ACK );
423 432
 	ack.block = htons ( state->block );
424 433
 	return udp_transmit ( state->server.sin_addr.s_addr,
425
-			      state->client.sin_port, state->server.sin_port,
434
+			      state->lport, state->server.sin_port,
426 435
 			      sizeof ( ack ), &ack );
427 436
 }
428 437
 
@@ -432,7 +441,7 @@ int tftp_ack_nowait ( struct tftp_state *state ) {
432 441
  * @v state				TFTP transfer state
433 442
  * @v tftp_state::server::sin_addr	TFTP server IP address
434 443
  * @v tftp_state::server::sin_port	TFTP server UDP port
435
- * @v tftp_state::client::sin_port	Client UDP port
444
+ * @v tftp_state::lport			Client UDP port
436 445
  * @v tftp_state::block			Most recently received block number
437 446
  * @ret True				Received a non-error response
438 447
  * @ret False				Received error response / no response
@@ -484,7 +493,7 @@ int tftp_ack ( struct tftp_state *state, union tftp_any **reply ) {
484 493
  * @v state				TFTP transfer state
485 494
  * @v tftp_state::server::sin_addr	TFTP server IP address
486 495
  * @v tftp_state::server::sin_port	TFTP server UDP port
487
- * @v tftp_state::client::sin_port	Client UDP port
496
+ * @v tftp_state::lport			Client UDP port
488 497
  * @v errcode				TFTP error code
489 498
  * @v errmsg				Descriptive error string, or NULL
490 499
  * @ret True				Error packet was sent
@@ -505,7 +514,7 @@ int tftp_error ( struct tftp_state *state, int errcode, const char *errmsg ) {
505 514
 	strncpy ( error.errmsg, errmsg ? errmsg : strerror ( errno ),
506 515
 		  sizeof ( error.errmsg ) );
507 516
 	return udp_transmit ( state->server.sin_addr.s_addr,
508
-			      state->client.sin_port, state->server.sin_port,
517
+			      state->lport, state->server.sin_port,
509 518
 			      sizeof ( error ), &error );
510 519
 }
511 520
 

Завантаження…
Відмінити
Зберегти