浏览代码

TFTP upgraded to use a core function library (in tftpcore.c) which will be

shared between TFTP, TFTM and MTFTP protocols.
tags/v0.9.3
Michael Brown 19 年前
父节点
当前提交
53a4436d94
共有 8 个文件被更改,包括 252 次插入195 次删除
  1. 0
    1
      src/include/etherboot.h
  2. 2
    1
      src/include/pxe.h
  3. 122
    39
      src/include/tftp.h
  4. 1
    1
      src/interface/pxe/pxe_tftp.c
  5. 1
    1
      src/proto/tcp.c
  6. 4
    0
      src/proto/tftm.c
  7. 87
    145
      src/proto/tftp.c
  8. 35
    7
      src/proto/tftpcore.c

+ 0
- 1
src/include/etherboot.h 查看文件

@@ -154,7 +154,6 @@ enum {
154 154
 #include	"udp.h"
155 155
 #include	"tcp.h"
156 156
 #include	"bootp.h"
157
-#include	"tftp.h"
158 157
 #include	"igmp.h"
159 158
 #include	"nfs.h"
160 159
 #include	"console.h"

+ 2
- 1
src/include/pxe.h 查看文件

@@ -4,6 +4,7 @@
4 4
 #include "pxe_types.h"
5 5
 #include "pxe_api.h"
6 6
 #include "etherboot.h"
7
+#include "tftp.h"
7 8
 
8 9
 /* Union used for PXE API calls; we don't know the type of the
9 10
  * structure until we interpret the opcode.  Also, Status is available
@@ -88,7 +89,7 @@ typedef struct pxe_stack {
88 89
 			uint32_t magic_cookie;
89 90
 			unsigned int len;
90 91
 			int eof;
91
-			char data[TFTP_MAX_PACKET];
92
+			char data[TFTP_MAX_BLKSIZE];
92 93
 		} tftpdata;
93 94
 		struct {
94 95
 			char *buffer;

+ 122
- 39
src/include/tftp.h 查看文件

@@ -1,13 +1,17 @@
1 1
 #ifndef	TFTP_H
2 2
 #define	TFTP_H
3 3
 
4
+/** @file */
5
+
4 6
 #include "in.h"
5 7
 #include "buffer.h"
6 8
 #include "nic.h"
9
+#include "ip.h"
10
+#include "udp.h"
7 11
 
8
-#define TFTP_PORT	69
9
-#define	TFTP_DEFAULTSIZE_PACKET	512
10
-#define	TFTP_MAX_PACKET		1432 /* 512 */
12
+#define TFTP_PORT	69		/**< Default TFTP server port */
13
+#define	TFTP_DEFAULT_BLKSIZE	512
14
+#define	TFTP_MAX_BLKSIZE		1432 /* 512 */
11 15
 
12 16
 #define TFTP_RRQ	1
13 17
 #define TFTP_WRQ	2
@@ -16,53 +20,132 @@
16 20
 #define TFTP_ERROR	5
17 21
 #define TFTP_OACK	6
18 22
 
19
-#define TFTP_CODE_EOF	1
20
-#define TFTP_CODE_MORE	2
21
-#define TFTP_CODE_ERROR	3
22
-#define TFTP_CODE_BOOT	4
23
-#define TFTP_CODE_CFG	5
23
+#define TFTP_ERR_FILE_NOT_FOUND	1 /**< File not found */
24
+#define TFTP_ERR_ACCESS_DENIED	2 /**< Access violation */
25
+#define TFTP_ERR_DISK_FULL	3 /**< Disk full or allocation exceeded */
26
+#define TFTP_ERR_ILLEGAL_OP	4 /**< Illegal TFTP operation */
27
+#define TFTP_ERR_UNKNOWN_TID	5 /**< Unknown transfer ID */
28
+#define TFTP_ERR_FILE_EXISTS	6 /**< File already exists */
29
+#define TFTP_ERR_UNKNOWN_USER	7 /**< No such user */
30
+#define TFTP_ERR_BAD_OPTS	8 /**< Option negotiation failed */
24 31
 
25
-struct tftp_t {
32
+/** A TFTP request (RRQ) packet */
33
+struct tftp_rrq {
34
+	struct iphdr ip;
35
+	struct udphdr udp;
36
+	uint16_t opcode;
37
+	char data[TFTP_DEFAULT_BLKSIZE];
38
+} PACKED;
39
+
40
+/** A TFTP data (DATA) packet */
41
+struct tftp_data {
42
+	struct iphdr ip;
43
+	struct udphdr udp;
44
+	uint16_t opcode;
45
+	uint16_t block;
46
+	uint8_t data[TFTP_MAX_BLKSIZE];
47
+} PACKED;
48
+ 
49
+/** A TFTP acknowledgement (ACK) packet */
50
+struct tftp_ack {
26 51
 	struct iphdr ip;
27 52
 	struct udphdr udp;
28 53
 	uint16_t opcode;
29
-	union {
30
-		uint8_t rrq[TFTP_DEFAULTSIZE_PACKET];
31
-		struct {
32
-			uint16_t block;
33
-			uint8_t  download[TFTP_MAX_PACKET];
34
-		} data;
35
-		struct {
36
-			uint16_t block;
37
-		} ack;
38
-		struct {
39
-			uint16_t errcode;
40
-			uint8_t  errmsg[TFTP_DEFAULTSIZE_PACKET];
41
-		} err;
42
-		struct {
43
-			uint8_t  data[TFTP_DEFAULTSIZE_PACKET+2];
44
-		} oack;
45
-	} u;
54
+	uint16_t block;
46 55
 } PACKED;
47 56
 
48
-/* define a smaller tftp packet solely for making requests to conserve stack
49
-   512 bytes should be enough */
50
-struct tftpreq_t {
57
+/** A TFTP error (ERROR) packet */
58
+struct tftp_error {
51 59
 	struct iphdr ip;
52 60
 	struct udphdr udp;
53 61
 	uint16_t opcode;
54
-	union {
55
-		uint8_t rrq[512];
56
-		struct {
57
-			uint16_t block;
58
-		} ack;
59
-		struct {
60
-			uint16_t errcode;
61
-			uint8_t  errmsg[512-2];
62
-		} err;
63
-	} u;
62
+	uint16_t errcode;
63
+	char errmsg[TFTP_DEFAULT_BLKSIZE];
64 64
 } PACKED;
65 65
 
66
+/** A TFTP options acknowledgement (OACK) packet */
67
+struct tftp_oack {
68
+	struct iphdr ip;
69
+	struct udphdr udp;
70
+	uint16_t opcode;
71
+	uint8_t data[TFTP_DEFAULT_BLKSIZE];
72
+} PACKED;
73
+
74
+/** The common header of all TFTP packets */
75
+struct tftp_common {
76
+	struct iphdr ip;
77
+	struct udphdr udp;
78
+	uint16_t opcode;
79
+} PACKED;
80
+
81
+/** A union encapsulating all TFTP packet types */
82
+union tftp_any {
83
+	struct tftp_common	common;
84
+	struct tftp_rrq		rrq;
85
+	struct tftp_data	data;
86
+	struct tftp_ack		ack;
87
+	struct tftp_error	error;
88
+	struct tftp_oack	oack;
89
+};	
90
+
91
+/**
92
+ * TFTP state
93
+ *
94
+ * This data structure holds the state for an ongoing TFTP transfer.
95
+ */
96
+struct tftp_state {
97
+	/** TFTP server address
98
+	 *
99
+	 * This is the IP address and UDP port from which data packets
100
+	 * will be sent, and to which ACK packets should be sent.
101
+	 */
102
+	struct sockaddr_in server;
103
+	/** TFTP client address
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.
108
+	 *
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.)
114
+	 */
115
+	struct sockaddr_in client;
116
+	/** Master client
117
+	 *
118
+	 * This will be true if the client is the master client for a
119
+	 * multicast protocol (i.e. MTFTP or TFTM).  (It will always
120
+	 * be true for a non-multicast protocol, i.e. plain old TFTP).
121
+	 */
122
+	int master;
123
+	/** Data block size
124
+	 *
125
+	 * This is the "blksize" option negotiated with the TFTP
126
+	 * server.  (If the TFTP server does not support TFTP options,
127
+	 * this will default to 512).
128
+	 */
129
+	unsigned int blksize;
130
+	/** File size
131
+	 *
132
+	 * This is the value returned in the "tsize" option from the
133
+	 * TFTP server.  If the TFTP server does not support the
134
+	 * "tsize" option, this value will be zero.
135
+	 */
136
+	off_t tsize;
137
+	/** Last received block
138
+	 *
139
+	 * The block number of the most recent block received from the
140
+	 * TFTP server.  Note that the first data block is block 1; a
141
+	 * value of 0 indicates that no data blocks have yet been
142
+	 * received.
143
+	 */
144
+	unsigned int block;
145
+};
146
+
147
+
148
+
66 149
 struct tftpreq_info_t {
67 150
 	struct sockaddr_in *server;
68 151
 	const char *name;

+ 1
- 1
src/interface/pxe/pxe_tftp.c 查看文件

@@ -131,7 +131,7 @@ PXENV_EXIT_t pxenv_tftp_open ( struct s_PXENV_TFTP_OPEN *tftp_open ) {
131 131
 	request.blksize = tftp_open->PacketSize;
132 132
 	DBG ( " %@:%d/%s (%d)", tftp_open->ServerIPAddress,
133 133
 	      tftp_open->TFTPPort, request.name, request.blksize );
134
-	if ( !request.blksize ) request.blksize = TFTP_DEFAULTSIZE_PACKET;
134
+	if ( !request.blksize ) request.blksize = TFTP_DEFAULT_BLKSIZE;
135 135
 	/* Make request and get first packet */
136 136
 	if ( !tftp_block ( &request, &block ) ) {
137 137
 		tftp_open->Status = PXENV_STATUS_TFTP_FILE_NOT_FOUND;

+ 1
- 1
src/proto/tcp.c 查看文件

@@ -1,7 +1,7 @@
1 1
 #include "etherboot.h"
2 2
 #include "ip.h"
3 3
 #include "tcp.h"
4
-
4
+#include "nic.h"
5 5
 
6 6
 void build_tcp_hdr(unsigned long destip, unsigned int srcsock,
7 7
 		  unsigned int destsock, long send_seq, long recv_seq,

+ 4
- 0
src/proto/tftm.c 查看文件

@@ -1,3 +1,5 @@
1
+#if 0
2
+
1 3
 /**************************************************************************
2 4
 *
3 5
 *    proto_tftm.c -- Etherboot Multicast TFTP 
@@ -481,3 +483,5 @@ static struct protocol tftm_protocol __protocol = {
481 483
 	.default_port = TFTM_PORT,
482 484
 	.load = url_tftm,
483 485
 };
486
+
487
+#endif

+ 87
- 145
src/proto/tftp.c 查看文件

@@ -1,169 +1,111 @@
1 1
 #include "etherboot.h"
2
-#include "in.h"
3
-#include "nic.h"
4 2
 #include "proto.h"
3
+#include "errno.h"
5 4
 #include "tftp.h"
5
+#include "tftpcore.h"
6 6
 
7
-/* Utility function for tftp_block() */
8
-static int await_tftp ( int ival, void *ptr __unused,
9
-			unsigned short ptype __unused, struct iphdr *ip,
10
-			struct udphdr *udp, struct tcphdr *tcp __unused ) {
11
-	if ( ! udp ) {
12
-		return 0;
13
-	}
14
-	if ( arptable[ARP_CLIENT].ipaddr.s_addr != ip->dest.s_addr )
15
-		return 0;
16
-	if ( ntohs ( udp->dest ) != ival )
17
-		return 0;
18
-	return 1;
19
-}
7
+/** @file
8
+ *
9
+ * TFTP protocol
10
+ */
20 11
 
21
-/*
22
- * Download a single block via TFTP.  This function is non-static so
23
- * that pxe_export.c can call it.
12
+/**
13
+ * Process a TFTP block
24 14
  *
25 15
  */
26
-int tftp_block ( struct tftpreq_info_t *request,
27
-		 struct tftpblk_info_t *block ) {
28
-	static struct sockaddr_in server;
29
-	static unsigned short lport = 2000; /* local port */
30
-	struct tftp_t *rcvd = NULL;
31
-	static struct tftpreq_t xmit;
32
-	static unsigned short xmitlen = 0;
33
-	static unsigned short blockidx = 0; /* Last block received */
34
-	static unsigned short retry = 0; /* Retry attempts on last block */
35
-	static int blksize = 0;
36
-	unsigned short recvlen = 0;
16
+static inline int process_tftp_data ( struct tftp_state *state,
17
+				      struct tftp_data *data,
18
+				      struct buffer *buffer,
19
+				      int *eof ) {
20
+	unsigned int blksize;
37 21
 
38
-	/* If this is a new request (i.e. if name is set), fill in
39
-	 * transmit block with RRQ and send it.
40
-	 */
41
-	if ( request ) {
42
-		rx_qdrain(); /* Flush receive queue */
43
-		xmit.opcode = htons(TFTP_RRQ);
44
-		xmitlen = (void*)&xmit.u.rrq - (void*)&xmit +
45
-			sprintf((char*)xmit.u.rrq, "%s%coctet%cblksize%c%d",
46
-				request->name, 0, 0, 0, request->blksize)
47
-			+ 1; /* null terminator */
48
-		blockidx = 0; /* Reset counters */
49
-		retry = 0;
50
-		blksize = TFTP_DEFAULTSIZE_PACKET;
51
-		lport++; /* Use new local port */
52
-		server = *(request->server);
53
-		if ( !udp_transmit(server.sin_addr.s_addr, lport,
54
-				   server.sin_port, xmitlen, &xmit) )
55
-			return (0);
22
+	/* Check it's the correct DATA block */
23
+	if ( ntohs ( data->block ) != ( state->block + 1 ) ) {
24
+		DBG ( "TFTP: got block %d, wanted block %d\n",
25
+		      ntohs ( data->block ), state->block + 1 );
26
+		return 1;
56 27
 	}
57
-	/* Exit if no transfer in progress */
58
-	if ( !blksize ) return (0);
59
-	/* Loop to wait until we get a packet we're interested in */
60
-	block->data = NULL; /* Used as flag */
61
-	while ( block->data == NULL ) {
62
-		long timeout = rfc2131_sleep_interval ( blockidx ? TFTP_REXMT :
63
-							TIMEOUT, retry );
64
-		if ( !await_reply(await_tftp, lport, NULL, timeout) ) {
65
-			/* No packet received */
66
-			if ( retry++ > MAX_TFTP_RETRIES ) break;
67
-			/* Retransmit last packet */
68
-			if ( !blockidx ) lport++; /* New lport if new RRQ */
69
-			if ( !udp_transmit(server.sin_addr.s_addr, lport,
70
-					   server.sin_port, xmitlen, &xmit) )
71
-				return (0);
72
-			continue; /* Back to waiting for packet */
73
-		}
74
-		/* Packet has been received */
75
-		rcvd = (struct tftp_t *)&nic.packet[ETH_HLEN];
76
-		recvlen = ntohs(rcvd->udp.len) - sizeof(struct udphdr)
77
-			- sizeof(rcvd->opcode);
78
-		server.sin_port = ntohs(rcvd->udp.src);
79
-		retry = 0; /* Reset retry counter */
80
-		switch ( htons(rcvd->opcode) ) {
81
-		case TFTP_ERROR : {
82
-			printf ( "TFTP error %d (%s)\n",
83
-				 ntohs(rcvd->u.err.errcode),
84
-				 rcvd->u.err.errmsg );
85
-			return (0); /* abort */
86
-		}
87
-		case TFTP_OACK : {
88
-			const char *p = rcvd->u.oack.data;
89
-			const char *e = p + recvlen - 10; /* "blksize\0\d\0" */
90
-
91
-			*((char*)(p+recvlen-1)) = '\0'; /* Force final 0 */
92
-			if ( blockidx || !request ) break; /* Too late */
93
-			if ( recvlen <= TFTP_MAX_PACKET ) /* sanity */ {
94
-				/* Check for blksize option honoured */
95
-				while ( p < e ) {
96
-					if ( strcasecmp("blksize",p) == 0 &&
97
-					     p[7] == '\0' ) {
98
-						blksize = strtoul(p+8,&p,10);
99
-						p++; /* skip null */
100
-					}
101
-					while ( *(p++) ) {};
102
-				}
103
-			}
104
-			if ( blksize < TFTP_DEFAULTSIZE_PACKET ||
105
-			     blksize > request->blksize ) {
106
-				/* Incorrect blksize - error and abort */
107
-				xmit.opcode = htons(TFTP_ERROR);
108
-				xmit.u.err.errcode = 8;
109
-				xmitlen = (void*)&xmit.u.err.errmsg
110
-					- (void*)&xmit
111
-					+ sprintf((char*)xmit.u.err.errmsg,
112
-						  "RFC1782 error")
113
-					+ 1;
114
-				udp_transmit(server.sin_addr.s_addr, lport,
115
-					     server.sin_port, xmitlen, &xmit);
116
-				return (0);
117
-			}
118
-		} break;
119
-		case TFTP_DATA :
120
-			if ( ntohs(rcvd->u.data.block) != ( blockidx + 1 ) )
121
-				break; /* Re-ACK last block sent */
122
-			if ( recvlen > ( blksize+sizeof(rcvd->u.data.block) ) )
123
-				break; /* Too large; ignore */
124
-			block->data = rcvd->u.data.download;
125
-			block->block = ++blockidx;
126
-			block->len = recvlen - sizeof(rcvd->u.data.block);
127
-			block->eof = ( (unsigned short)block->len < blksize );
128
-			/* If EOF, zero blksize to indicate transfer done */
129
-			if ( block->eof ) blksize = 0;
130
-			break;
131
-	        default: break;	/* Do nothing */
132
-		}
133
-		/* Send ACK */
134
-		xmit.opcode = htons(TFTP_ACK);
135
-		xmit.u.ack.block = htons(blockidx);
136
-		xmitlen = TFTP_MIN_PACKET;
137
-		udp_transmit ( server.sin_addr.s_addr, lport, server.sin_port,
138
-			       xmitlen, &xmit );
28
+	/* Check it's an acceptable size */
29
+	blksize = ( ntohs ( data->udp.len )
30
+		    + offsetof ( typeof ( *data ), udp )
31
+		    - offsetof ( typeof ( *data ), data ) );
32
+	if ( blksize > state->blksize ) {
33
+		DBG ( "TFTP: oversized block size %d (max %d)\n",
34
+		      blksize, state->blksize );
35
+		return 1;
139 36
 	}
140
-	return ( block->data ? 1 : 0 );
37
+	/* Place block in the buffer */
38
+	if ( ! fill_buffer ( buffer, data->data, state->block * state->blksize,
39
+			     blksize ) ) {
40
+		DBG ( "TFTP: could not place data in buffer: %m\n" );
41
+		return 0;
42
+	}
43
+	/* Increment block counter */
44
+	state->block++;
45
+	/* Set EOF marker */
46
+	*eof = ( blksize < state->blksize );
47
+	return 1;
141 48
 }
142 49
 
143
-/*
50
+/**
144 51
  * Download a file via TFTP
145 52
  *
146 53
  */
147 54
 int tftp ( char *url __unused, struct sockaddr_in *server, char *file,
148 55
 	   struct buffer *buffer ) {
149
-	struct tftpreq_info_t request_data = {
150
-		.server = server,
151
-		.name = file,
152
-		.blksize = TFTP_MAX_PACKET,
153
-	};
154
-	struct tftpreq_info_t *request = &request_data;
155
-	struct tftpblk_info_t block;
156
-	off_t offset = 0;
56
+	struct tftp_state state;
57
+	union tftp_any *reply;
58
+	int eof = 0;
59
+
60
+	/* Initialise TFTP state */
61
+	memset ( &state, 0, sizeof ( state ) );
62
+	state.server = *server;
63
+	
64
+	/* Open the file */
65
+	if ( ! tftp_open ( &state, file, &reply ) ) {
66
+		DBG ( "TFTP: could not open %@:%d/%s : %m\n",
67
+		      server->sin_addr.s_addr, server->sin_port, file );
68
+		return 0;
69
+	}
70
+	
71
+	/* Process OACK, if any */
72
+	if ( ntohs ( reply->common.opcode ) == TFTP_OACK ) {
73
+		if ( ! tftp_process_opts ( &state, &reply->oack ) ) {
74
+			DBG ( "TFTP: option processing failed : %m\n" );
75
+			return 0;
76
+		}
77
+		reply = NULL;
78
+	}
157 79
 
80
+	/* Fetch file, a block at a time */
158 81
 	do {
159
-		if ( ! tftp_block ( request, &block ) )
82
+		/* Get next block to process.  (On the first time
83
+		 * through, we may already have a block from
84
+		 * tftp_open()).
85
+		 */
86
+		if ( ! reply ) {
87
+			if ( ! tftp_ack ( &state, &reply ) ) {
88
+				DBG ( "TFTP: could not get next block: %m\n" );
89
+				return 0;
90
+			}
91
+		}
92
+		twiddle();
93
+		/* Check it's a DATA block */
94
+		if ( ntohs ( reply->common.opcode ) != TFTP_DATA ) {
95
+			DBG ( "TFTP: unexpected opcode %d\n",
96
+			      ntohs ( reply->common.opcode ) );
97
+			errno = PXENV_STATUS_TFTP_UNKNOWN_OPCODE;
160 98
 			return 0;
161
-		if ( ! fill_buffer ( buffer, block.data, offset, block.len ) )
99
+		}
100
+		/* Process the DATA block */
101
+		if ( ! process_tftp_data ( &state, &reply->data, buffer,
102
+					   &eof ) )
162 103
 			return 0;
163
-		twiddle();
164
-		offset += block.len;
165
-		request = NULL; /* Send request only once */
166
-	} while ( ! block.eof );
104
+		reply = NULL;
105
+	} while ( ! eof );
106
+
107
+	/* ACK the final packet, as a courtesy to the server */
108
+	tftp_ack_nowait ( &state );
167 109
 
168 110
 	return 1;
169 111
 }

+ 35
- 7
src/proto/tftpcore.c 查看文件

@@ -47,21 +47,32 @@ int await_tftp ( int ival __unused, void *ptr, unsigned short ptype __unused,
47 47
 
48 48
 	/* Must have valid UDP (and, therefore, also IP) headers */
49 49
 	if ( ! udp ) {
50
+		DBG2 ( "TFTPCORE: not UDP\n" );
50 51
 		return 0;
51 52
 	}
52 53
 	/* Packet must come from the TFTP server */
53
-	if ( ip->src.s_addr != state->server.sin_addr.s_addr )
54
+	if ( ip->src.s_addr != state->server.sin_addr.s_addr ) {
55
+		DBG2 ( "TFTPCORE: from %@, not from TFTP server %@\n",
56
+		       ip->src.s_addr, state->server.sin_addr.s_addr );
54 57
 		return 0;
58
+	}
55 59
 	/* Packet must be addressed to the correct UDP port */
56
-	if ( ntohs ( udp->dest ) != state->client.sin_port )
60
+	if ( ntohs ( udp->dest ) != state->client.sin_port ) {
61
+		DBG2 ( "TFTPCORE: to UDP port %d, not to TFTP port %d\n",
62
+		       ntohs ( udp->dest ), state->client.sin_port );
57 63
 		return 0;
64
+	}
58 65
 	/* Packet must be addressed to us, or to our multicast
59 66
 	 * listening address (if we have one).
60 67
 	 */
61 68
 	if ( ! ( ( ip->dest.s_addr == arptable[ARP_CLIENT].ipaddr.s_addr ) ||
62 69
 		 ( ( state->client.sin_addr.s_addr ) && 
63
-		   ( ip->dest.s_addr == state->client.sin_addr.s_addr ) ) ) )
70
+		   ( ip->dest.s_addr == state->client.sin_addr.s_addr ) ) ) ) {
71
+		DBG2 ( "TFTPCORE: to %@, not to %@ (or %@)\n",
72
+		       ip->dest.s_addr, arptable[ARP_CLIENT].ipaddr.s_addr,
73
+		       state->client.sin_addr.s_addr );
64 74
 		return 0;
75
+	}
65 76
 	return 1;
66 77
 }
67 78
 
@@ -164,7 +175,7 @@ int tftp_open ( struct tftp_state *state, const char *filename,
164 175
 		state->server.sin_port = TFTP_PORT;
165 176
 
166 177
 	/* Determine whether or not to use lport */
167
-	fixed_lport = state->server.sin_port;
178
+	fixed_lport = state->client.sin_port;
168 179
 
169 180
 	/* Set up RRQ */
170 181
 	rrq.opcode = htons ( TFTP_RRQ );
@@ -202,7 +213,11 @@ int tftp_open ( struct tftp_state *state, const char *filename,
202 213
 		if ( await_reply ( await_tftp, 0, state, timeout ) ) {
203 214
 			*reply = ( union tftp_any * ) &nic.packet[ETH_HLEN];
204 215
 			state->server.sin_port =
205
-				ntohs ( (*reply)->common.udp.dest );
216
+				ntohs ( (*reply)->common.udp.src );
217
+			DBG ( "TFTPCORE: got reply from %@:%d (type %d)\n",
218
+			      state->server.sin_addr.s_addr,
219
+			      state->server.sin_port,
220
+			      ntohs ( (*reply)->common.opcode ) );
206 221
 			if ( ntohs ( (*reply)->common.opcode ) == TFTP_ERROR ){
207 222
 				tftp_set_errno ( &(*reply)->error );
208 223
 				return 0;
@@ -211,6 +226,7 @@ int tftp_open ( struct tftp_state *state, const char *filename,
211 226
 		}
212 227
 	}
213 228
 
229
+	DBG ( "TFTPCORE: open request timed out\n" );
214 230
 	errno = PXENV_STATUS_TFTP_OPEN_TIMEOUT;
215 231
 	return 0;
216 232
 }
@@ -250,6 +266,8 @@ int tftp_process_opts ( struct tftp_state *state, struct tftp_oack *oack ) {
250 266
 	const char *p;
251 267
 	const char *end;
252 268
 
269
+	DBG ( "TFTPCORE: processing OACK\n" );
270
+
253 271
 	/* End of options */
254 272
 	end = ( ( char * ) &oack->udp ) + ntohs ( oack->udp.len );
255 273
 
@@ -266,6 +284,7 @@ int tftp_process_opts ( struct tftp_state *state, struct tftp_oack *oack ) {
266 284
 				return 0;
267 285
 			}
268 286
 			p++;
287
+			DBG ( "TFTPCORE: got blksize %d\n", state->blksize );
269 288
 		} else if ( strcasecmp ( "tsize", p ) == 0 ) {
270 289
 			p += 6;
271 290
 			state->tsize = strtoul ( p, &p, 10 );
@@ -275,6 +294,7 @@ int tftp_process_opts ( struct tftp_state *state, struct tftp_oack *oack ) {
275 294
 				return 0;
276 295
 			}
277 296
 			p++;
297
+			DBG ( "TFTPCORE: got tsize %d\n", state->tsize );
278 298
 		} else if ( strcasecmp ( "multicast", p ) == 0 ) {
279 299
 			char *e = strchr ( p, ',' );
280 300
 			if ( ( ! e ) || ( e >= end ) ) {
@@ -317,7 +337,12 @@ int tftp_process_opts ( struct tftp_state *state, struct tftp_oack *oack ) {
317 337
 				return 0;
318 338
 			}
319 339
 			p++;
340
+			DBG ( "TFTPCORE: got multicast %@:%d (%s)\n",
341
+			      state->client.sin_addr.s_addr,
342
+			      state->client.sin_port,
343
+			      ( state->master ? "master" : "not master" ) );
320 344
 		} else {
345
+			DBG ( "TFTPCORE: unknown option \"%s\"\n", p );
321 346
 			p += strlen ( p ) + 1; /* skip option name */
322 347
 			p += strlen ( p ) + 1; /* skip option value */
323 348
 		}
@@ -351,6 +376,7 @@ int tftp_process_opts ( struct tftp_state *state, struct tftp_oack *oack ) {
351 376
 int tftp_ack_nowait ( struct tftp_state *state ) {
352 377
 	struct tftp_ack ack;
353 378
 
379
+	DBG ( "TFTPCORE: acknowledging data block %d\n", state->block );
354 380
 	ack.opcode = htons ( TFTP_ACK );
355 381
 	ack.block = htons ( state->block );
356 382
 	return udp_transmit ( state->server.sin_addr.s_addr,
@@ -396,9 +422,11 @@ int tftp_ack ( struct tftp_state *state, union tftp_any **reply ) {
396 422
 			DBG ( "TFTP: could not send ACK: %m\n" );
397 423
 			return 0;
398 424
 		}	
399
-		if ( await_reply ( await_tftp, 0, &state, timeout ) ) {
425
+		if ( await_reply ( await_tftp, 0, state, timeout ) ) {
400 426
 			/* We received a reply */
401 427
 			*reply = ( union tftp_any * ) &nic.packet[ETH_HLEN];
428
+			DBG ( "TFTPCORE: got reply (type %d)\n",
429
+			      ntohs ( (*reply)->common.opcode ) );
402 430
 			if ( ntohs ( (*reply)->common.opcode ) == TFTP_ERROR ){
403 431
 				tftp_set_errno ( &(*reply)->error );
404 432
 				return 0;
@@ -406,7 +434,7 @@ int tftp_ack ( struct tftp_state *state, union tftp_any **reply ) {
406 434
 			return 1;
407 435
 		}
408 436
 	}
409
-	DBG ( "TFTP: ACK retries exceeded\n" );
437
+	DBG ( "TFTP: timed out during read\n" );
410 438
 	errno = PXENV_STATUS_TFTP_READ_TIMEOUT;
411 439
 	return 0;
412 440
 }

正在加载...
取消
保存