Преглед на файлове

Add tftp_ack() and tftp_error()

tags/v0.9.3
Michael Brown преди 19 години
родител
ревизия
7d63b39e3d
променени са 1 файла, в които са добавени 73 реда и са изтрити 7 реда
  1. 73
    7
      src/proto/tftpcore.c

+ 73
- 7
src/proto/tftpcore.c Целия файл

@@ -25,10 +25,20 @@
25 25
  * (i.e. comes from the TFTP server, has the correct destination port,
26 26
  * and is addressed either to our IP address or to our multicast
27 27
  * listening address).
28
+ *
29
+ * Invoke await_tftp() using code such as
30
+ *
31
+ * @code
32
+ *
33
+ * if ( await_reply ( await_tftp, 0, &tftp_state, timeout ) ) {
34
+ *	...
35
+ * }
36
+ *
37
+ * @endcode
28 38
  */
29
-static int await_tftp ( int ival __unused, void *ptr,
30
-			unsigned short ptype __unused, struct iphdr *ip,
31
-			struct udphdr *udp, struct tcphdr *tcp __unused ) {
39
+int await_tftp ( int ival __unused, void *ptr, unsigned short ptype __unused,
40
+		 struct iphdr *ip, struct udphdr *udp,
41
+		 struct tcphdr *tcp __unused ) {
32 42
 	struct tftp_state *state = ptr;
33 43
 
34 44
 	/* Must have valid UDP (and, therefore, also IP) headers */
@@ -55,13 +65,13 @@ static int await_tftp ( int ival __unused, void *ptr,
55 65
 /**
56 66
  * Issue a TFTP open request (RRQ)
57 67
  *
58
- * @v filename				File name
59 68
  * @v state				TFTP transfer state
60 69
  * @v tftp_state::server::sin_addr	TFTP server IP address
61 70
  * @v tftp_state::server::sin_port	TFTP server UDP port, or 0
62 71
  * @v tftp_state::client::sin_addr	Client multicast IP address, or 0.0.0.0
63 72
  * @v tftp_state::client::sin_port	Client UDP port, or 0
64 73
  * @v tftp_state::blksize		Requested blksize, or 0
74
+ * @v filename				File name
65 75
  * @ret True				Received a non-error response
66 76
  * @ret False				Received error response / no response
67 77
  * @ret tftp_state::client::sin_port	Client UDP port
@@ -120,7 +130,7 @@ static int await_tftp ( int ival __unused, void *ptr,
120 130
  * leave_group() at appropriate times.
121 131
  *
122 132
  */
123
-int tftp_open ( const char *filename, struct tftp_state *state,
133
+int tftp_open ( struct tftp_state *state, const char *filename,
124 134
 		union tftp_any **tftp ) {
125 135
 	static unsigned short lport = 2000; /* local port */
126 136
 	int fixed_lport;
@@ -165,6 +175,9 @@ int tftp_open ( const char *filename, struct tftp_state *state,
165 175
 			state->client.sin_port = ++lport;
166 176
 		
167 177
 		/* Send the RRQ */
178
+		DBG ( "TFTPCORE: requesting %@:%d/%s from port %d\n",
179
+		      state->server.sin_addr.s_addr, state->server.sin_port,
180
+		      rrq.data, state->client.sin_port );
168 181
 		if ( ! udp_transmit ( state->server.sin_addr.s_addr,
169 182
 				      state->client.sin_port,
170 183
 				      state->server.sin_port,
@@ -185,8 +198,8 @@ int tftp_open ( const char *filename, struct tftp_state *state,
185 198
 /**
186 199
  * Process a TFTP OACK packet
187 200
  *
188
- * @v oack				The TFTP OACK packet
189 201
  * @v state				TFTP transfer state
202
+ * @v oack				The TFTP OACK packet
190 203
  * @ret True				Options were processed successfully
191 204
  * @ret False				Options were not processed successfully
192 205
  * @ret tftp_state::blksize		Negotiated blksize
@@ -213,7 +226,7 @@ int tftp_open ( const char *filename, struct tftp_state *state,
213 226
  * #TFTP_DEFAULT_BLKSIZE before returning, you probably don't need to
214 227
  * worry about this.
215 228
  */
216
-int tftp_process_opts ( struct tftp_oack *oack, struct tftp_state *state ) {
229
+int tftp_process_opts ( struct tftp_state *state, struct tftp_oack *oack ) {
217 230
 	const char *p;
218 231
 	const char *end;
219 232
 
@@ -297,3 +310,56 @@ int tftp_process_opts ( struct tftp_oack *oack, struct tftp_state *state ) {
297 310
 
298 311
 	return 1;
299 312
 }
313
+
314
+/**
315
+ * Acknowledge a TFTP packet
316
+ *
317
+ * @v state				TFTP transfer state
318
+ * @v tftp_state::server::sin_addr	TFTP server IP address
319
+ * @v tftp_state::server::sin_port	TFTP server UDP port
320
+ * @v tftp_state::client::sin_port	Client UDP port
321
+ * @v tftp_state::block			Most recently received block number
322
+ * @ret True				Acknowledgement packet was sent
323
+ * @ret False				Acknowledgement packet was not sent
324
+ * 
325
+ * Send a TFTP ACK packet for the most recently received block.
326
+ *
327
+ * This sends only a single ACK packet; it does not wait for the
328
+ * server's response.
329
+ */
330
+int tftp_ack ( struct tftp_state *state ) {
331
+	struct tftp_ack ack;
332
+
333
+	ack.opcode = htons ( TFTP_ACK );
334
+	ack.block = htons ( state->block );
335
+	return udp_transmit ( state->server.sin_addr.s_addr,
336
+			      state->client.sin_port, state->server.sin_port,
337
+			      sizeof ( ack ), &ack );
338
+}
339
+
340
+/**
341
+ * Send a TFTP error
342
+ *
343
+ * @v state				TFTP transfer state
344
+ * @v tftp_state::server::sin_addr	TFTP server IP address
345
+ * @v tftp_state::server::sin_port	TFTP server UDP port
346
+ * @v tftp_state::client::sin_port	Client UDP port
347
+ * @v err				TFTP error code
348
+ * @v errmsg				Descriptive error string
349
+ * @ret True				Error packet was sent
350
+ * @ret False				Error packet was not sent
351
+ *
352
+ * Send a TFTP ERROR packet back to the server to terminate the
353
+ * transfer.
354
+ */
355
+int tftp_error ( struct tftp_state *state, int err, const char *errmsg ) {
356
+	struct tftp_error error;
357
+
358
+	DBG ( "TFTPCORE: aborting with error %d (%s)\n", err, errmsg );
359
+	error.opcode = htons ( TFTP_ERROR );
360
+	error.errcode = htons ( err );
361
+	strncpy ( error.errmsg, errmsg, sizeof ( error.errmsg ) );
362
+	return udp_transmit ( state->server.sin_addr.s_addr,
363
+			      state->client.sin_port, state->server.sin_port,
364
+			      sizeof ( error ), &error );
365
+}

Loading…
Отказ
Запис