Pārlūkot izejas kodu

Warnings purge

tags/v0.9.3
Marty Connor 17 gadus atpakaļ
vecāks
revīzija
b234d4a13e
4 mainītis faili ar 15 papildinājumiem un 764 dzēšanām
  1. 10
    10
      src/proto/igmp.c
  2. 5
    5
      src/proto/nfs.c
  3. 0
    208
      src/proto/tftm.c
  4. 0
    541
      src/proto/tftpcore.c

+ 10
- 10
src/proto/igmp.c Parādīt failu

@@ -3,11 +3,11 @@
3 3
  *
4 4
  */
5 5
 
6
-#include "ip.h"
7
-#include "igmp.h"
8
-#include "background.h"
9
-#include "nic.h"
10
-#include "etherboot.h"
6
+#include <ip.h>
7
+#include <igmp.h>
8
+#include <background.h>
9
+#include <nic.h>
10
+#include <etherboot.h>
11 11
 
12 12
 static unsigned long last_igmpv1 = 0;
13 13
 static struct igmptable_t igmptable[MAX_IGMP];
@@ -50,8 +50,7 @@ static void send_igmp_reports ( unsigned long now ) {
50 50
 		igmp.igmp.chksum = ipchksum ( &igmp.igmp,
51 51
 					      sizeof ( igmp.igmp ) );
52 52
 		ip_transmit ( sizeof ( igmp ), &igmp );
53
-		DBG ( "IGMP sent report to %@\n",
54
-		      igmp.igmp.group.s_addr );
53
+		DBG ( "IGMP sent report to %s\n", inet_ntoa ( igmp.igmp.group ) );
55 54
 		/* Don't send another igmp report until asked */
56 55
 		igmptable[i].time = 0;
57 56
 	}
@@ -84,7 +83,7 @@ static void process_igmp ( unsigned long now, unsigned short ptype __unused,
84 83
 			interval = ( igmp->response_time * TICKS_PER_SEC ) /10;
85 84
 		}
86 85
 		
87
-		DBG ( "IGMP received query for %@\n", igmp->group.s_addr );
86
+		DBG ( "IGMP received query for %s\n", inet_ntoa ( igmp->group ) );
88 87
 		for ( i = 0 ; i < MAX_IGMP ; i++ ) {
89 88
 			uint32_t group = igmptable[i].group.s_addr;
90 89
 			if ( ( group == 0 ) ||
@@ -101,7 +100,8 @@ static void process_igmp ( unsigned long now, unsigned short ptype __unused,
101 100
 	if ( ( ( igmp->type == IGMPv1_REPORT ) ||
102 101
 	       ( igmp->type == IGMPv2_REPORT ) ) &&
103 102
 	     ( ip->dest.s_addr == igmp->group.s_addr ) ) {
104
-		DBG ( "IGMP received report for %@\n", igmp->group.s_addr);
103
+	        DBG ( "IGMP received report for %s\n", 
104
+		      inet_ntoa ( igmp->group ) );
105 105
 		for ( i = 0 ; i < MAX_IGMP ; i++ ) {
106 106
 			if ( ( igmptable[i].group.s_addr ==
107 107
 			       igmp->group.s_addr ) &&
@@ -142,7 +142,7 @@ void leave_group ( int slot ) {
142 142
 		igmp.igmp.group.s_addr = igmptable[slot].group.s_addr;
143 143
 		igmp.igmp.chksum = ipchksum ( &igmp.igmp, sizeof ( igmp ) );
144 144
 		ip_transmit ( sizeof ( igmp ), &igmp );
145
-		DBG ( "IGMP left group %@\n", igmp.igmp.group.s_addr );
145
+		DBG ( "IGMP left group %s\n", inet_ntoa ( igmp.igmp.group ) );
146 146
 	}
147 147
 	memset ( &igmptable[slot], 0, sizeof ( igmptable[0] ) );
148 148
 }

+ 5
- 5
src/proto/nfs.c Parādīt failu

@@ -49,7 +49,7 @@ static void rpc_printerror(struct rpc_t *rpc)
49 49
 	    rpc->u.reply.astatus) {
50 50
 		/* rpc_printerror() is called for any RPC related error,
51 51
 		 * suppress output if no low level RPC error happened.  */
52
-		DBG("RPC error: (%d,%d,%d)\n", ntohl(rpc->u.reply.rstatus),
52
+		DBG("RPC error: (%ld,%ld,%ld)\n", ntohl(rpc->u.reply.rstatus),
53 53
 		    ntohl(rpc->u.reply.verifier),
54 54
 		    ntohl(rpc->u.reply.astatus));
55 55
 	}
@@ -503,14 +503,14 @@ static int nfs ( char *url __unused, struct sockaddr_in *server,
503 503
 	mount_server.sin_addr = nfs_server.sin_addr = server->sin_addr;
504 504
 	mount_server.sin_port = rpc_lookup(server, PROG_MOUNT, 1, sport);
505 505
 	if ( ! mount_server.sin_port ) {
506
-		DBG ( "Cannot get mount port from %!:%d\n",
507
-		      server->sin_addr.s_addr, server->sin_port );
506
+		DBG ( "Cannot get mount port from %s:%d\n",
507
+		      inet_ntoa ( server->sin_addr ), server->sin_port );
508 508
 		return 0;
509 509
 	}
510 510
 	nfs_server.sin_port = rpc_lookup(server, PROG_NFS, 2, sport);
511 511
 	if ( ! mount_server.sin_port ) {
512
-		DBG ( "Cannot get nfs port from %!:%d\n",
513
-		      server->sin_addr.s_addr, server->sin_port );
512
+		DBG ( "Cannot get nfs port from %s:%d\n",
513
+		      inet_ntoa ( server->sin_addr ), server->sin_port );
514 514
 		return 0;
515 515
 	}
516 516
 

+ 0
- 208
src/proto/tftm.c Parādīt failu

@@ -1,208 +0,0 @@
1
-#include "etherboot.h"
2
-#include "proto.h"
3
-#include "errno.h"
4
-#include "tftp.h"
5
-#include "tftpcore.h"
6
-
7
-/** @file
8
- *
9
- * TFTM protocol
10
- *
11
- * TFTM is a protocol defined in RFC2090 as a multicast extension to
12
- * TFTP.
13
- */
14
-
15
-static inline int tftm_process_opts ( struct tftp_state *state,
16
-				      struct tftp_oack *oack ) {
17
-	struct in_addr old_mcast_addr = state->multicast.sin_addr;
18
-
19
-	if ( ! tftp_process_opts ( state, oack ) )
20
-		return 0;
21
-
22
-	if ( old_mcast_addr.s_addr != state->multicast.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->multicast.sin_addr.s_addr );
30
-		join_group ( IGMP_SERVER, state->multicast.sin_addr.s_addr );
31
-	}
32
-
33
-	DBG ( "TFTM: I am a %s client\n",
34
-	      ( state->master ? "master" : "slave" ) );
35
-
36
-	return 1;
37
-}
38
-
39
-
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;
45
-
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;
51
-
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;
58
-	}
59
-
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;
64
-	}
65
-
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
-	}
72
-
73
-	/* Record the last received block */
74
-	state->block = ntohs ( data->block );
75
-
76
-	return 1;
77
-}
78
-
79
-
80
-static inline int tftm_next ( struct tftp_state *state,
81
-			      union tftp_any **reply,
82
-			      struct buffer *buffer ) {
83
-	long listen_timeout;
84
-
85
-	listen_timeout = rfc2131_sleep_interval ( TIMEOUT, MAX_TFTP_RETRIES );
86
-
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;
94
-		}
95
-		if ( *reply ) {
96
-			/* Received an error packet */
97
-			return 0;
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
-}
108
-
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
-	}
149
-
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;
161
-			}
162
-			break;
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;
170
-			}
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;
178
-		}
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;
190
-		}
191
-	}
192
-
193
-	/* ACK the final packet, as a courtesy to the server */
194
-	tftp_ack_nowait ( &state );
195
-
196
-	rc = 1;
197
- out:
198
-	if ( state.multicast.sin_addr.s_addr ) {
199
-		leave_group ( IGMP_SERVER );
200
-	}
201
-	return rc;
202
-}
203
-
204
-static struct protocol tftm_protocol __protocol = {
205
-	.name = "x-tftm",
206
-	.default_port = TFTP_PORT,
207
-	.load = tftm,
208
-};

+ 0
- 541
src/proto/tftpcore.c Parādīt failu

@@ -1,541 +0,0 @@
1
-#include "tftp.h"
2
-#include "old_tcp.h" /* for struct tcphdr */
3
-#include "errno.h"
4
-#include "etherboot.h"
5
-#include "tftpcore.h"
6
-
7
-/** @file */
8
-
9
-/**
10
- * await_reply() filter for TFTP packets
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::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
21
- *
22
- * Wait for a TFTP packet that is part of the current connection
23
- * (i.e. comes from the TFTP server, has the correct destination port,
24
- * and is addressed either to our IP address and UDP port, or to our
25
- * multicast listening address and UDP port).
26
- *
27
- * Use await_tftp() in code such as
28
- *
29
- * @code
30
- *
31
- * if ( await_reply ( await_tftp, 0, &tftp_state, timeout ) ) {
32
- *	...
33
- * }
34
- *
35
- * @endcode
36
- */
37
-static int await_tftp ( int ival __unused, void *ptr,
38
-			unsigned short ptype __unused, struct iphdr *ip,
39
-			struct udphdr *udp, struct tcphdr *tcp __unused ) {
40
-	struct tftp_state *state = ptr;
41
-
42
-	/* Must have valid UDP (and, therefore, also IP) headers */
43
-	if ( ! udp ) {
44
-		DBG2 ( "TFTPCORE: not UDP\n" );
45
-		return 0;
46
-	}
47
-	/* Packet must come from the TFTP server */
48
-	if ( ip->src.s_addr != state->server.sin_addr.s_addr ) {
49
-		DBG2 ( "TFTPCORE: from %@, not from TFTP server %@\n",
50
-		       ip->src.s_addr, state->server.sin_addr.s_addr );
51
-		return 0;
52
-	}
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;
59
-	}
60
-	/* Packet may be addressed to our multicast IP address and UDP
61
-	 * port, if we have one
62
-	 */
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;
67
-	}
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;
73
-}
74
-
75
-/**
76
- * Retrieve a TFTP packet
77
- *
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()
89
- *
90
- * Retrieve the next packet sent by the TFTP server, if any is sent
91
- * within the specified timeout period.  The packet is returned via
92
- * #reply.  If no packet is received within the timeout period, a NULL
93
- * value will be stored in #reply.
94
- *
95
- * If the response from the server is a TFTP ERROR packet, tftp_get()
96
- * will return False and #errno will be set accordingly.
97
- *
98
- * You can differentiate between "received no response" and "received
99
- * an error response" by checking #reply; if #reply is NULL then no
100
- * response was received.
101
- */
102
-int tftp_get ( struct tftp_state *state, long timeout,
103
-	       union tftp_any **reply ) {
104
-
105
-	*reply = NULL;
106
-
107
-	if ( ! await_reply ( await_tftp, 0, state, timeout ) ) {
108
-		errno = PXENV_STATUS_TFTP_READ_TIMEOUT;
109
-		return 0;
110
-	}
111
-
112
-	*reply = ( union tftp_any * ) &nic.packet[ETH_HLEN];
113
-	DBG ( "TFTPCORE: got reply (type %d)\n",
114
-	      ntohs ( (*reply)->common.opcode ) );
115
-	if ( ntohs ( (*reply)->common.opcode ) == TFTP_ERROR ){
116
-		tftp_set_errno ( &(*reply)->error );
117
-		return 0;
118
-	}
119
-	return 1;
120
-}
121
-
122
-/**
123
- * Issue a TFTP open request (RRQ)
124
- *
125
- * @v state				TFTP transfer state
126
- * @v tftp_state::server::sin_addr	TFTP server IP address
127
- * @v tftp_state::server::sin_port	TFTP server 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
131
- * @v tftp_state::blksize		Requested blksize, or 0
132
- * @v filename				File name
133
- * @v multicast				Enable/disable rfc2090 multicast TFTP
134
- * @ret True				Received a non-error response
135
- * @ret False				Received error response / no response
136
- * @ret tftp_state::server::sin_port	TFTP server UDP port
137
- * @ret tftp_state::lport		Client UDP port
138
- * @ret tftp_state::blksize		Always #TFTP_DEFAULT_BLKSIZE
139
- * @ret *reply				The server's response, if any
140
- * @err #PXENV_STATUS_TFTP_OPEN_TIMEOUT	TFTP open timed out
141
- * @err other				As returned by udp_transmit()
142
- * @err other				As set by tftp_set_errno()
143
- *
144
- * Send a TFTP/TFTM/MTFTP RRQ (read request) to a TFTP server, and
145
- * return the server's reply (which may be an OACK, DATA or ERROR
146
- * packet).  The server's reply will not be acknowledged, or processed
147
- * in any way.
148
- *
149
- * If tftp_state::server::sin_port is 0, the standard TFTP server port
150
- * (#TFTP_PORT) will be used.
151
- *
152
- * If tftp_state::lport is 0, the standard mechanism of
153
- * using a new, unique port number for each TFTP request will be used.
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
- *
159
- * For the various different types of TFTP server, you should treat
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.
181
- *
182
- * If tftp_state::blksize is 0, the maximum blocksize
183
- * (#TFTP_MAX_BLKSIZE) will be requested.
184
- *
185
- * On exit, tftp_state::blksize will always contain
186
- * #TFTP_DEFAULT_BLKSIZE, since this is the blocksize value that must
187
- * be assumed until the OACK packet is processed (by a subsequent call
188
- * to tftp_process_opts()).
189
- *
190
- * tftp_state::server::sin_port will be set to the UDP port from which
191
- * the server's response originated.  This may or may not be the port
192
- * to which the open request was sent.
193
- *
194
- * The options "blksize" and "tsize" will always be appended to a TFTP
195
- * open request.  The option "multicast" will be appended to the
196
- * request if #multicast is True.  Servers that do not understand any
197
- * of these options should simply ignore them.
198
- *
199
- * tftp_open() will not automatically join or leave multicast groups;
200
- * the caller is responsible for calling join_group() and
201
- * leave_group() at appropriate times.
202
- *
203
- * If the response from the server is a TFTP ERROR packet, tftp_open()
204
- * will return False and #errno will be set accordingly.
205
- */
206
-int tftp_open ( struct tftp_state *state, const char *filename,
207
-		union tftp_any **reply, int multicast ) {
208
-	static unsigned short lport = 2000; /* local port */
209
-	int fixed_lport;
210
-	struct tftp_rrq rrq;
211
-	char *p;
212
-	unsigned int rrqlen;
213
-	int retry;
214
-
215
-	/* Flush receive queue */
216
-	rx_qdrain();
217
-
218
-	/* Default to blksize of TFTP_MAX_BLKSIZE if none specified */
219
-	if ( ! state->blksize )
220
-		state->blksize = TFTP_MAX_BLKSIZE;
221
-
222
-	/* Use default TFTP server port if none specified */
223
-	if ( ! state->server.sin_port )
224
-		state->server.sin_port = TFTP_PORT;
225
-
226
-	/* Determine whether or not to use lport */
227
-	fixed_lport = state->lport;
228
-
229
-	/* Set up RRQ */
230
-	rrq.opcode = htons ( TFTP_RRQ );
231
-	p = rrq.data;
232
-	p += sprintf ( p, "%s%coctet%cblksize%c%d%ctsize%c0",
233
-		       filename, 0, 0, 0, state->blksize, 0, 0 ) + 1;
234
-	if ( multicast ) {
235
-		p += sprintf ( p, "multicast%c", 0 ) + 1;
236
-	}
237
-	rrqlen = ( p - ( char * ) &rrq );
238
-
239
-	/* Set negotiated blksize to default value */
240
-	state->blksize = TFTP_DEFAULT_BLKSIZE;
241
-	
242
-	/* Nullify received packet pointer */
243
-	*reply = NULL;
244
-
245
-	/* Transmit RRQ until we get a response */
246
-	for ( retry = 0 ; retry < MAX_TFTP_RETRIES ; retry++ ) {
247
-		long timeout = rfc2131_sleep_interval ( TIMEOUT, retry );
248
-
249
-		/* Set client UDP port, if not already fixed */
250
-		if ( ! fixed_lport )
251
-			state->lport = ++lport;
252
-		
253
-		/* Send the RRQ */
254
-		DBG ( "TFTPCORE: requesting %@:%d/%s from port %d\n",
255
-		      state->server.sin_addr.s_addr, state->server.sin_port,
256
-		      rrq.data, state->lport );
257
-		if ( ! udp_transmit ( state->server.sin_addr.s_addr,
258
-				      state->lport, state->server.sin_port,
259
-				      rrqlen, &rrq ) )
260
-			return 0;
261
-		
262
-		/* Wait for response */
263
-		if ( tftp_get ( state, timeout, reply ) ) {
264
-			/* We got a non-error response */
265
-			state->server.sin_port
266
-				= ntohs ( (*reply)->common.udp.src );
267
-			DBG ( "TFTP server is at %@:%d\n",
268
-			      state->server.sin_addr.s_addr,
269
-			      state->server.sin_port );
270
-			return 1;
271
-		}
272
-		if ( *reply ) {
273
-			/* We got an error response; abort */
274
-			return 0;
275
-		}
276
-	}
277
-
278
-	DBG ( "TFTPCORE: open request timed out\n" );
279
-	errno = PXENV_STATUS_TFTP_OPEN_TIMEOUT;
280
-	return 0;
281
-}
282
-
283
-/**
284
- * Process a TFTP OACK packet
285
- *
286
- * @v state				TFTP transfer state
287
- * @v oack				The TFTP OACK packet
288
- * @ret True				Options were processed successfully
289
- * @ret False				Options were not processed successfully
290
- * @ret tftp_state::blksize		Negotiated blksize
291
- * @ret tftp_state::tsize		File size (if known), or 0
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
294
- * @ret tftp_state::master		Client is master
295
- * @err EINVAL				An invalid option value was encountered
296
- *
297
- * Process the options returned by the TFTP server in an rfc2347 OACK
298
- * packet.  The options "blksize" (rfc2348), "tsize" (rfc2349) and
299
- * "multicast" (rfc2090) are recognised and processed; any other
300
- * options are silently ignored.
301
- *
302
- * Where an option is not present in the OACK packet, the
303
- * corresponding field(s) in #state will be left unaltered.
304
- *
305
- * Calling tftp_process_opts() does not send an acknowledgement for
306
- * the OACK packet; this is the responsibility of the caller.
307
- *
308
- * @note If the "blksize" option is not present, tftp_state::blksize
309
- * will @b not be implicitly set to #TFTP_DEFAULT_BLKSIZE.  However,
310
- * since tftp_open() always sets tftp_state::blksize to
311
- * #TFTP_DEFAULT_BLKSIZE before returning, you probably don't need to
312
- * worry about this.
313
- */
314
-int tftp_process_opts ( struct tftp_state *state, struct tftp_oack *oack ) {
315
-	const char *p;
316
-	const char *end;
317
-
318
-	DBG ( "TFTPCORE: processing OACK\n" );
319
-
320
-	/* End of options */
321
-	end = ( ( char * ) &oack->udp ) + ntohs ( oack->udp.len );
322
-
323
-	/* Only possible error */
324
-	errno = EINVAL;
325
-
326
-	for ( p = oack->data ; p < end ; ) {
327
-		if ( strcasecmp ( "blksize", p ) == 0 ) {
328
-			p += 8;
329
-			state->blksize = strtoul ( p, &p, 10 );
330
-			if ( *p ) {
331
-				DBG ( "TFTPCORE: garbage \"%s\" "
332
-				      "after blksize\n", p );
333
-				return 0;
334
-			}
335
-			p++;
336
-			DBG ( "TFTPCORE: got blksize %d\n", state->blksize );
337
-		} else if ( strcasecmp ( "tsize", p ) == 0 ) {
338
-			p += 6;
339
-			state->tsize = strtoul ( p, &p, 10 );
340
-			if ( *p ) {
341
-				DBG ( "TFTPCORE: garbage \"%s\" "
342
-				      "after tsize\n", p );
343
-				return 0;
344
-			}
345
-			p++;
346
-			DBG ( "TFTPCORE: got tsize %d\n", state->tsize );
347
-		} else if ( strcasecmp ( "multicast", p ) == 0 ) {
348
-			p += 10;
349
-			char *e = strchr ( p, ',' );
350
-			if ( ( ! e ) || ( e >= end ) ) {
351
-				DBG ( "TFTPCORE: malformed multicast field "
352
-				      "\"%s\"\n", p );
353
-				return 0;
354
-			}
355
-			/* IP address may be missing, in which case we
356
-			 * should leave state->multicast.sin_addr
357
-			 * unaltered.
358
-			 */
359
-			if ( e != p ) {
360
-				int rc;
361
-				*e = '\0';
362
-				rc = inet_aton ( p,
363
-						 &state->multicast.sin_addr );
364
-				*e = ',';
365
-				if ( ! rc ) {
366
-					DBG ( "TFTPCORE: malformed multicast "
367
-					      "IP address \"%s\"\n", p );
368
-					return 0;
369
-				}
370
-			}
371
-			p = e + 1;
372
-			/* UDP port may also be missing */
373
-			if ( *p != ',' ) {
374
-				state->multicast.sin_port
375
-					= strtoul ( p, &p, 10 );
376
-				if ( *p != ',' ) {
377
-					DBG ( "TFTPCORE: garbage \"%s\" "
378
-					      "after multicast port\n", p );
379
-					return 0;
380
-				}
381
-			}
382
-			p++;
383
-			/* "Master Client" must always be present */
384
-			state->master = strtoul ( p, &p, 10 );
385
-			if ( *p ) {
386
-				DBG ( "TFTPCORE: garbage \"%s\" "
387
-				      "after multicast mc\n", p );
388
-				return 0;
389
-			}
390
-			p++;
391
-			DBG ( "TFTPCORE: got multicast %@:%d (%s)\n",
392
-			      state->multicast.sin_addr.s_addr,
393
-			      state->multicast.sin_port,
394
-			      ( state->master ? "master" : "not master" ) );
395
-		} else {
396
-			DBG ( "TFTPCORE: unknown option \"%s\"\n", p );
397
-			p += strlen ( p ) + 1; /* skip option name */
398
-			p += strlen ( p ) + 1; /* skip option value */
399
-		}
400
-	}
401
-
402
-	if ( p > end ) {
403
-		DBG ( "TFTPCORE: overran options in OACK\n" );
404
-		return 0;
405
-	}
406
-
407
-	return 1;
408
-}
409
-
410
-/**
411
- * Acknowledge a TFTP packet
412
- *
413
- * @v state				TFTP transfer state
414
- * @v tftp_state::server::sin_addr	TFTP server IP address
415
- * @v tftp_state::server::sin_port	TFTP server UDP port
416
- * @v tftp_state::lport			Client UDP port
417
- * @v tftp_state::block			Most recently received block number
418
- * @ret True				Acknowledgement packet was sent
419
- * @ret False				Acknowledgement packet was not sent
420
- * @err other				As returned by udp_transmit()
421
- * 
422
- * Send a TFTP ACK packet for the most recently received block.
423
- *
424
- * This sends only a single ACK packet; it does not wait for the
425
- * server's response.
426
- */
427
-int tftp_ack_nowait ( struct tftp_state *state ) {
428
-	struct tftp_ack ack;
429
-
430
-	DBG ( "TFTPCORE: acknowledging data block %d\n", state->block );
431
-	ack.opcode = htons ( TFTP_ACK );
432
-	ack.block = htons ( state->block );
433
-	return udp_transmit ( state->server.sin_addr.s_addr,
434
-			      state->lport, state->server.sin_port,
435
-			      sizeof ( ack ), &ack );
436
-}
437
-
438
-/**
439
- * Acknowledge a TFTP packet and wait for a response
440
- *
441
- * @v state				TFTP transfer state
442
- * @v tftp_state::server::sin_addr	TFTP server IP address
443
- * @v tftp_state::server::sin_port	TFTP server UDP port
444
- * @v tftp_state::lport			Client UDP port
445
- * @v tftp_state::block			Most recently received block number
446
- * @ret True				Received a non-error response
447
- * @ret False				Received error response / no response
448
- * @ret *reply				The server's response, if any
449
- * @err #PXENV_STATUS_TFTP_READ_TIMEOUT	Timed out waiting for a response
450
- * @err other				As returned by tftp_ack_nowait()
451
- * @err other				As set by tftp_set_errno()
452
- *
453
- * Send a TFTP ACK packet for the most recently received data block,
454
- * and keep transmitting this ACK until we get a response from the
455
- * server (e.g. a new data block).
456
- *
457
- * If the response is a TFTP DATA packet, no processing is done.
458
- * Specifically, the block number is not checked to ensure that this
459
- * is indeed the next data block in the sequence, nor is
460
- * tftp_state::block updated with the new block number.
461
- *
462
- * If the response from the server is a TFTP ERROR packet, tftp_open()
463
- * will return False and #errno will be set accordingly.
464
- */
465
-int tftp_ack ( struct tftp_state *state, union tftp_any **reply ) {
466
-	int retry;
467
-
468
-	*reply = NULL;
469
-	for ( retry = 0 ; retry < MAX_TFTP_RETRIES ; retry++ ) {
470
-		long timeout = rfc2131_sleep_interval ( TFTP_REXMT, retry );
471
-		/* ACK the last data block */
472
-		if ( ! tftp_ack_nowait ( state ) ) {
473
-			DBG ( "TFTP: could not send ACK: %m\n" );
474
-			return 0;
475
-		}
476
-		if ( tftp_get ( state, timeout, reply ) ) {
477
-			/* We got a non-error response */
478
-			return 1;
479
-		}
480
-		if ( *reply ) {
481
-			/* We got an error response */
482
-			return 0;
483
-		}
484
-	}
485
-	DBG ( "TFTP: timed out during read\n" );
486
-	errno = PXENV_STATUS_TFTP_READ_TIMEOUT;
487
-	return 0;
488
-}
489
-
490
-/**
491
- * Send a TFTP error
492
- *
493
- * @v state				TFTP transfer state
494
- * @v tftp_state::server::sin_addr	TFTP server IP address
495
- * @v tftp_state::server::sin_port	TFTP server UDP port
496
- * @v tftp_state::lport			Client UDP port
497
- * @v errcode				TFTP error code
498
- * @v errmsg				Descriptive error string, or NULL
499
- * @ret True				Error packet was sent
500
- * @ret False				Error packet was not sent
501
- *
502
- * Send a TFTP ERROR packet back to the server to terminate the
503
- * transfer.
504
- *
505
- * If #errmsg is NULL, the current error message string as returned by
506
- * strerror(errno) will be used as the error text.
507
- */
508
-int tftp_error ( struct tftp_state *state, int errcode, const char *errmsg ) {
509
-	struct tftp_error error;
510
-
511
-	DBG ( "TFTPCORE: aborting with error %d (%s)\n", errcode, errmsg );
512
-	error.opcode = htons ( TFTP_ERROR );
513
-	error.errcode = htons ( errcode );
514
-	strncpy ( error.errmsg, errmsg ? errmsg : strerror ( errno ),
515
-		  sizeof ( error.errmsg ) );
516
-	return udp_transmit ( state->server.sin_addr.s_addr,
517
-			      state->lport, state->server.sin_port,
518
-			      sizeof ( error ), &error );
519
-}
520
-
521
-/**
522
- * Interpret a TFTP error
523
- *
524
- * @v error				Pointer to a struct tftp_error
525
- *
526
- * Sets #errno based on the error code in a TFTP ERROR packet.
527
- */
528
-void tftp_set_errno ( struct tftp_error *error ) {
529
-	static int errmap[] = {
530
-		[TFTP_ERR_FILE_NOT_FOUND] = PXENV_STATUS_TFTP_FILE_NOT_FOUND,
531
-		[TFTP_ERR_ACCESS_DENIED] = PXENV_STATUS_TFTP_ACCESS_VIOLATION,
532
-		[TFTP_ERR_ILLEGAL_OP] = PXENV_STATUS_TFTP_UNKNOWN_OPCODE,
533
-	};
534
-	unsigned int errcode = ntohs ( error->errcode );
535
-	
536
-	errno = 0;
537
-	if ( errcode < ( sizeof(errmap) / sizeof(errmap[0]) ) )
538
-		errno = errmap[errcode];
539
-	if ( ! errno )
540
-		errno = PXENV_STATUS_TFTP_ERROR_OPCODE;
541
-}

Notiek ielāde…
Atcelt
Saglabāt