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

[proto] Remove unsupported NFS protocol

The NFS protocol code came from legacy Etherboot and was never updated
to work as a gPXE protocol.  There has been no demand for this protocol,
so this patch removes it.

I have an unfinished NFSv3 over TCP implementation for gPXE that can be
used as the base for new work, should we want to resurrect this
protocol.

Signed-off-by: Stefan Hajnoczi <stefanha@gmail.com>
Signed-off-by: Marty Connor <mdc@etherboot.org>
tags/v1.0.0
Stefan Hajnoczi преди 15 години
родител
ревизия
1548189ffa
променени са 6 файла, в които са добавени 1 реда и са изтрити 685 реда
  1. 0
    3
      src/config/config.c
  2. 0
    1
      src/config/general.h
  3. 0
    1
      src/core/main.c
  4. 1
    1
      src/core/settings.c
  5. 0
    63
      src/include/nfs.h
  6. 0
    616
      src/proto/nfs.c

+ 0
- 3
src/config/config.c Целия файл

@@ -109,9 +109,6 @@ REQUIRE_OBJECT ( pxe_call );
109 109
 #ifdef DOWNLOAD_PROTO_TFTP
110 110
 REQUIRE_OBJECT ( tftp );
111 111
 #endif
112
-#ifdef DOWNLOAD_PROTO_NFS
113
-REQUIRE_OBJECT ( nfs );
114
-#endif
115 112
 #ifdef DOWNLOAD_PROTO_HTTP
116 113
 REQUIRE_OBJECT ( http );
117 114
 #endif

+ 0
- 1
src/config/general.h Целия файл

@@ -54,7 +54,6 @@ FILE_LICENCE ( GPL2_OR_LATER );
54 54
  */
55 55
 
56 56
 #define	DOWNLOAD_PROTO_TFTP	/* Trivial File Transfer Protocol */
57
-#undef	DOWNLOAD_PROTO_NFS	/* Network File System */
58 57
 #define	DOWNLOAD_PROTO_HTTP	/* Hypertext Transfer Protocol */
59 58
 #undef	DOWNLOAD_PROTO_HTTPS	/* Secure Hypertext Transfer Protocol */
60 59
 #undef	DOWNLOAD_PROTO_FTP	/* File Transfer Protocol */

+ 0
- 1
src/core/main.c Целия файл

@@ -9,7 +9,6 @@ Literature dealing with the network protocols:
9 9
 	DHCP - RFC2131, RFC2132 (options)
10 10
 	TFTP - RFC1350, RFC2347 (options), RFC2348 (blocksize), RFC2349 (tsize)
11 11
 	RPC - RFC1831, RFC1832 (XDR), RFC1833 (rpcbind/portmapper)
12
-	NFS - RFC1094, RFC1813 (v3, useful for clarifications, not implemented)
13 12
 	IGMP - RFC1112
14 13
 
15 14
 **************************************************************************/

+ 1
- 1
src/core/settings.c Целия файл

@@ -1426,7 +1426,7 @@ struct setting filename_setting __setting = {
1426 1426
 /** Root path setting */
1427 1427
 struct setting root_path_setting __setting = {
1428 1428
 	.name = "root-path",
1429
-	.description = "NFS/iSCSI root path",
1429
+	.description = "iSCSI root path",
1430 1430
 	.tag = DHCP_ROOT_PATH,
1431 1431
 	.type = &setting_type_string,
1432 1432
 };

+ 0
- 63
src/include/nfs.h Целия файл

@@ -1,63 +0,0 @@
1
-#ifndef	_NFS_H
2
-#define	_NFS_H
3
-
4
-#define SUNRPC_PORT	111
5
-
6
-#define PROG_PORTMAP	100000
7
-#define PROG_NFS	100003
8
-#define PROG_MOUNT	100005
9
-
10
-#define MSG_CALL	0
11
-#define MSG_REPLY	1
12
-
13
-#define PORTMAP_GETPORT	3
14
-
15
-#define MOUNT_ADDENTRY	1
16
-#define MOUNT_UMOUNTALL	4
17
-
18
-#define NFS_LOOKUP	4
19
-#define	NFS_READLINK	5
20
-#define NFS_READ	6
21
-
22
-#define NFS_FHSIZE	32
23
-
24
-#define NFSERR_PERM	1
25
-#define NFSERR_NOENT	2
26
-#define NFSERR_ACCES	13
27
-#define	NFSERR_ISDIR	21
28
-#define	NFSERR_INVAL	22
29
-
30
-/* Block size used for NFS read accesses.  A RPC reply packet (including  all
31
- * headers) must fit within a single Ethernet frame to avoid fragmentation.
32
- * Chosen to be a power of two, as most NFS servers are optimized for this.  */
33
-#define NFS_READ_SIZE	1024
34
-
35
-#define NFS_MAXLINKDEPTH 16
36
-
37
-struct rpc_t {
38
-	struct iphdr ip;
39
-	struct udphdr udp;
40
-	union {
41
-		uint8_t  data[300];		/* longest RPC call must fit!!!! */
42
-		struct {
43
-			uint32_t id;
44
-			uint32_t type;
45
-			uint32_t rpcvers;
46
-			uint32_t prog;
47
-			uint32_t vers;
48
-			uint32_t proc;
49
-			uint32_t data[1];
50
-		} call;
51
-		struct {
52
-			uint32_t id;
53
-			uint32_t type;
54
-			uint32_t rstatus;
55
-			uint32_t verifier;
56
-			uint32_t v2;
57
-			uint32_t astatus;
58
-			uint32_t data[1];
59
-		} reply;
60
-	} u;
61
-} PACKED;
62
-
63
-#endif	/* _NFS_H */

+ 0
- 616
src/proto/nfs.c Целия файл

@@ -1,616 +0,0 @@
1
-#if 0
2
-
3
-#include <gpxe/init.h>
4
-#include <gpxe/in.h>
5
-
6
-/* NOTE: the NFS code is heavily inspired by the NetBSD netboot code (read:
7
- * large portions are copied verbatim) as distributed in OSKit 0.97.  A few
8
- * changes were necessary to adapt the code to Etherboot and to fix several
9
- * inconsistencies.  Also the RPC message preparation is done "by hand" to
10
- * avoid adding netsprintf() which I find hard to understand and use.  */
11
-
12
-/* NOTE 2: Etherboot does not care about things beyond the kernel image, so
13
- * it loads the kernel image off the boot server (ARP_SERVER) and does not
14
- * access the client root disk (root-path in dhcpd.conf), which would use
15
- * ARP_ROOTSERVER.  The root disk is something the operating system we are
16
- * about to load needs to use.  This is different from the OSKit 0.97 logic.  */
17
-
18
-/* NOTE 3: Symlink handling introduced by Anselm M Hoffmeister, 2003-July-14
19
- * If a symlink is encountered, it is followed as far as possible (recursion
20
- * possible, maximum 16 steps). There is no clearing of ".."'s inside the
21
- * path, so please DON'T DO THAT. thx. */
22
-
23
-#define START_OPORT 700		/* mountd usually insists on secure ports */
24
-#define OPORT_SWEEP 200		/* make sure we don't leave secure range */
25
-
26
-static int oport = START_OPORT;
27
-static struct sockaddr_in mount_server;
28
-static struct sockaddr_in nfs_server;
29
-static unsigned long rpc_id;
30
-
31
-/**************************************************************************
32
-RPC_INIT - set up the ID counter to something fairly random
33
-**************************************************************************/
34
-void rpc_init(void)
35
-{
36
-	unsigned long t;
37
-
38
-	t = currticks();
39
-	rpc_id = t ^ (t << 8) ^ (t << 16);
40
-}
41
-
42
-/**************************************************************************
43
-RPC_PRINTERROR - Print a low level RPC error message
44
-**************************************************************************/
45
-static void rpc_printerror(struct rpc_t *rpc)
46
-{
47
-	if (rpc->u.reply.rstatus || rpc->u.reply.verifier ||
48
-	    rpc->u.reply.astatus) {
49
-		/* rpc_printerror() is called for any RPC related error,
50
-		 * suppress output if no low level RPC error happened.  */
51
-		DBG("RPC error: (%ld,%ld,%ld)\n", ntohl(rpc->u.reply.rstatus),
52
-		    ntohl(rpc->u.reply.verifier),
53
-		    ntohl(rpc->u.reply.astatus));
54
-	}
55
-}
56
-
57
-/**************************************************************************
58
-AWAIT_RPC - Wait for an rpc packet
59
-**************************************************************************/
60
-static int await_rpc(int ival, void *ptr,
61
-		     unsigned short ptype __unused, struct iphdr *ip,
62
-		     struct udphdr *udp, struct tcphdr *tcp __unused)
63
-{
64
-	struct rpc_t *rpc;
65
-	if (!udp) 
66
-		return 0;
67
-	if (arptable[ARP_CLIENT].ipaddr.s_addr != ip->dest.s_addr)
68
-		return 0;
69
-	if (ntohs(udp->dest) != ival)
70
-		return 0;
71
-	if (nic.packetlen < ETH_HLEN + sizeof(struct iphdr) + sizeof(struct udphdr) + 8)
72
-		return 0;
73
-	rpc = (struct rpc_t *)&nic.packet[ETH_HLEN];
74
-	if (*(unsigned long *)ptr != ntohl(rpc->u.reply.id))
75
-		return 0;
76
-	if (MSG_REPLY != ntohl(rpc->u.reply.type))
77
-		return 0;
78
-	return 1;
79
-}
80
-
81
-/**************************************************************************
82
-RPC_LOOKUP - Lookup RPC Port numbers
83
-**************************************************************************/
84
-static int rpc_lookup(struct sockaddr_in *addr, int prog, int ver, int sport)
85
-{
86
-	struct rpc_t buf, *rpc;
87
-	unsigned long id;
88
-	int retries;
89
-	long *p;
90
-
91
-	id = rpc_id++;
92
-	buf.u.call.id = htonl(id);
93
-	buf.u.call.type = htonl(MSG_CALL);
94
-	buf.u.call.rpcvers = htonl(2);	/* use RPC version 2 */
95
-	buf.u.call.prog = htonl(PROG_PORTMAP);
96
-	buf.u.call.vers = htonl(2);	/* portmapper is version 2 */
97
-	buf.u.call.proc = htonl(PORTMAP_GETPORT);
98
-	p = (long *)buf.u.call.data;
99
-	*p++ = 0; *p++ = 0;				/* auth credential */
100
-	*p++ = 0; *p++ = 0;				/* auth verifier */
101
-	*p++ = htonl(prog);
102
-	*p++ = htonl(ver);
103
-	*p++ = htonl(IP_UDP);
104
-	*p++ = 0;
105
-	for (retries = 0; retries < MAX_RPC_RETRIES; retries++) {
106
-		long timeout;
107
-		udp_transmit(addr->sin_addr.s_addr, sport, addr->sin_port,
108
-			(char *)p - (char *)&buf, &buf);
109
-		timeout = rfc2131_sleep_interval(TIMEOUT, retries);
110
-		if (await_reply(await_rpc, sport, &id, timeout)) {
111
-			rpc = (struct rpc_t *)&nic.packet[ETH_HLEN];
112
-			if (rpc->u.reply.rstatus || rpc->u.reply.verifier ||
113
-			    rpc->u.reply.astatus) {
114
-				rpc_printerror(rpc);
115
-				return 0;
116
-			} else {
117
-				return ntohl(rpc->u.reply.data[0]);
118
-			}
119
-		}
120
-	}
121
-	return 0;
122
-}
123
-
124
-/**************************************************************************
125
-RPC_ADD_CREDENTIALS - Add RPC authentication/verifier entries
126
-**************************************************************************/
127
-static long *rpc_add_credentials(long *p)
128
-{
129
-	int hl;
130
-
131
-	/* Here's the executive summary on authentication requirements of the
132
-	 * various NFS server implementations:  Linux accepts both AUTH_NONE
133
-	 * and AUTH_UNIX authentication (also accepts an empty hostname field
134
-	 * in the AUTH_UNIX scheme).  *BSD refuses AUTH_NONE, but accepts
135
-	 * AUTH_UNIX (also accepts an empty hostname field in the AUTH_UNIX
136
-	 * scheme).  To be safe, use AUTH_UNIX and pass the hostname if we have
137
-	 * it (if the BOOTP/DHCP reply didn't give one, just use an empty
138
-	 * hostname).  */
139
-
140
-	hl = (hostnamelen + 3) & ~3;
141
-
142
-	/* Provide an AUTH_UNIX credential.  */
143
-	*p++ = htonl(1);		/* AUTH_UNIX */
144
-	*p++ = htonl(hl+20);		/* auth length */
145
-	*p++ = htonl(0);		/* stamp */
146
-	*p++ = htonl(hostnamelen);	/* hostname string */
147
-	if (hostnamelen & 3) {
148
-		*(p + hostnamelen / 4) = 0; /* add zero padding */
149
-	}
150
-	memcpy(p, hostname, hostnamelen);
151
-	p += hl / 4;
152
-	*p++ = 0;			/* uid */
153
-	*p++ = 0;			/* gid */
154
-	*p++ = 0;			/* auxiliary gid list */
155
-
156
-	/* Provide an AUTH_NONE verifier.  */
157
-	*p++ = 0;			/* AUTH_NONE */
158
-	*p++ = 0;			/* auth length */
159
-
160
-	return p;
161
-}
162
-
163
-/**************************************************************************
164
-NFS_PRINTERROR - Print a NFS error message
165
-**************************************************************************/
166
-static void nfs_printerror(int err)
167
-{
168
-	switch (-err) {
169
-	case NFSERR_PERM:
170
-		printf("Not owner\n");
171
-		break;
172
-	case NFSERR_NOENT:
173
-		printf("No such file or directory\n");
174
-		break;
175
-	case NFSERR_ACCES:
176
-		printf("Permission denied\n");
177
-		break;
178
-	case NFSERR_ISDIR:
179
-		printf("Directory given where filename expected\n");
180
-		break;
181
-	case NFSERR_INVAL:
182
-		printf("Invalid filehandle\n");
183
-		break; // INVAL is not defined in NFSv2, some NFS-servers
184
-		// seem to use it in answers to v2 nevertheless.
185
-	case 9998:
186
-		printf("low-level RPC failure (parameter decoding problem?)\n");
187
-		break;
188
-	case 9999:
189
-		printf("low-level RPC failure (authentication problem?)\n");
190
-		break;
191
-	default:
192
-		printf("Unknown NFS error %d\n", -err);
193
-	}
194
-}
195
-
196
-/**************************************************************************
197
-NFS_MOUNT - Mount an NFS Filesystem
198
-**************************************************************************/
199
-static int nfs_mount(struct sockaddr_in *server, char *path, char *fh, int sport)
200
-{
201
-	struct rpc_t buf, *rpc;
202
-	unsigned long id;
203
-	int retries;
204
-	long *p;
205
-	int pathlen = strlen(path);
206
-
207
-	id = rpc_id++;
208
-	buf.u.call.id = htonl(id);
209
-	buf.u.call.type = htonl(MSG_CALL);
210
-	buf.u.call.rpcvers = htonl(2);	/* use RPC version 2 */
211
-	buf.u.call.prog = htonl(PROG_MOUNT);
212
-	buf.u.call.vers = htonl(1);	/* mountd is version 1 */
213
-	buf.u.call.proc = htonl(MOUNT_ADDENTRY);
214
-	p = rpc_add_credentials((long *)buf.u.call.data);
215
-	*p++ = htonl(pathlen);
216
-	if (pathlen & 3) {
217
-		*(p + pathlen / 4) = 0;	/* add zero padding */
218
-	}
219
-	memcpy(p, path, pathlen);
220
-	p += (pathlen + 3) / 4;
221
-	for (retries = 0; retries < MAX_RPC_RETRIES; retries++) {
222
-		long timeout;
223
-		udp_transmit(server->sin_addr.s_addr, sport, server->sin_port,
224
-			(char *)p - (char *)&buf, &buf);
225
-		timeout = rfc2131_sleep_interval(TIMEOUT, retries);
226
-		if (await_reply(await_rpc, sport, &id, timeout)) {
227
-			rpc = (struct rpc_t *)&nic.packet[ETH_HLEN];
228
-			if (rpc->u.reply.rstatus || rpc->u.reply.verifier ||
229
-			    rpc->u.reply.astatus || rpc->u.reply.data[0]) {
230
-				rpc_printerror(rpc);
231
-				if (rpc->u.reply.rstatus) {
232
-					/* RPC failed, no verifier, data[0] */
233
-					return -9999;
234
-				}
235
-				if (rpc->u.reply.astatus) {
236
-					/* RPC couldn't decode parameters */
237
-					return -9998;
238
-				}
239
-				return -ntohl(rpc->u.reply.data[0]);
240
-			} else {
241
-				memcpy(fh, rpc->u.reply.data + 1, NFS_FHSIZE);
242
-				return 0;
243
-			}
244
-		}
245
-	}
246
-	return -1;
247
-}
248
-
249
-/**************************************************************************
250
-NFS_UMOUNTALL - Unmount all our NFS Filesystems on the Server
251
-**************************************************************************/
252
-static void nfs_umountall(struct sockaddr_in *server)
253
-{
254
-	struct rpc_t buf, *rpc;
255
-	unsigned long id;
256
-	int retries;
257
-	long *p;
258
-
259
-	id = rpc_id++;
260
-	buf.u.call.id = htonl(id);
261
-	buf.u.call.type = htonl(MSG_CALL);
262
-	buf.u.call.rpcvers = htonl(2);	/* use RPC version 2 */
263
-	buf.u.call.prog = htonl(PROG_MOUNT);
264
-	buf.u.call.vers = htonl(1);	/* mountd is version 1 */
265
-	buf.u.call.proc = htonl(MOUNT_UMOUNTALL);
266
-	p = rpc_add_credentials((long *)buf.u.call.data);
267
-	for (retries = 0; retries < MAX_RPC_RETRIES; retries++) {
268
-		long timeout = rfc2131_sleep_interval(TIMEOUT, retries);
269
-		udp_transmit(server->sin_addr.s_addr, oport, server->sin_port,
270
-			(char *)p - (char *)&buf, &buf);
271
-		if (await_reply(await_rpc, oport, &id, timeout)) {
272
-			rpc = (struct rpc_t *)&nic.packet[ETH_HLEN];
273
-			if (rpc->u.reply.rstatus || rpc->u.reply.verifier ||
274
-			    rpc->u.reply.astatus) {
275
-				rpc_printerror(rpc);
276
-			}
277
-			break;
278
-		}
279
-	}
280
-}
281
-
282
-/**************************************************************************
283
-NFS_RESET - Reset the NFS subsystem
284
-**************************************************************************/
285
-static void nfs_reset ( void ) {
286
-	/* If we have a mount server, call nfs_umountall() */
287
-	if ( mount_server.sin_addr.s_addr ) {
288
-		nfs_umountall ( &mount_server );
289
-	}
290
-	/* Zero the data structures */
291
-	memset ( &mount_server, 0, sizeof ( mount_server ) );
292
-	memset ( &nfs_server, 0, sizeof ( nfs_server ) );
293
-}
294
-
295
-/***************************************************************************
296
- * NFS_READLINK (AH 2003-07-14)
297
- * This procedure is called when read of the first block fails -
298
- * this probably happens when it's a directory or a symlink
299
- * In case of successful readlink(), the dirname is manipulated,
300
- * so that inside the nfs() function a recursion can be done.
301
- **************************************************************************/
302
-static int nfs_readlink(struct sockaddr_in *server, char *fh __unused,
303
-			char *path, char *nfh, int sport)
304
-{
305
-	struct rpc_t buf, *rpc;
306
-	unsigned long id;
307
-	long *p;
308
-	int retries;
309
-	int pathlen = strlen(path);
310
-
311
-	id = rpc_id++;
312
-	buf.u.call.id = htonl(id);
313
-	buf.u.call.type = htonl(MSG_CALL);
314
-	buf.u.call.rpcvers = htonl(2);	/* use RPC version 2 */
315
-	buf.u.call.prog = htonl(PROG_NFS);
316
-	buf.u.call.vers = htonl(2);	/* nfsd is version 2 */
317
-	buf.u.call.proc = htonl(NFS_READLINK);
318
-	p = rpc_add_credentials((long *)buf.u.call.data);
319
-	memcpy(p, nfh, NFS_FHSIZE);
320
-	p += (NFS_FHSIZE / 4);
321
-	for (retries = 0; retries < MAX_RPC_RETRIES; retries++) {
322
-		long timeout = rfc2131_sleep_interval(TIMEOUT, retries);
323
-		udp_transmit(server->sin_addr.s_addr, sport, server->sin_port,
324
-			(char *)p - (char *)&buf, &buf);
325
-		if (await_reply(await_rpc, sport, &id, timeout)) {
326
-			rpc = (struct rpc_t *)&nic.packet[ETH_HLEN];
327
-			if (rpc->u.reply.rstatus || rpc->u.reply.verifier ||
328
-			    rpc->u.reply.astatus || rpc->u.reply.data[0]) {
329
-				rpc_printerror(rpc);
330
-				if (rpc->u.reply.rstatus) {
331
-					/* RPC failed, no verifier, data[0] */
332
-					return -9999;
333
-				}
334
-				if (rpc->u.reply.astatus) {
335
-					/* RPC couldn't decode parameters */
336
-					return -9998;
337
-				}
338
-				return -ntohl(rpc->u.reply.data[0]);
339
-			} else {
340
-				// It *is* a link.
341
-				// If it's a relative link, append everything to dirname, filename TOO!
342
-				retries = strlen ( (char *)(&(rpc->u.reply.data[2]) ));
343
-				if ( *((char *)(&(rpc->u.reply.data[2]))) != '/' ) {
344
-					path[pathlen++] = '/';
345
-					while ( ( retries + pathlen ) > 298 ) {
346
-						retries--;
347
-					}
348
-					if ( retries > 0 ) {
349
-						memcpy(path + pathlen, &(rpc->u.reply.data[2]), retries + 1);
350
-					} else { retries = 0; }
351
-					path[pathlen + retries] = 0;
352
-				} else {
353
-					// Else make it the only path.
354
-					if ( retries > 298 ) { retries = 298; }
355
-					memcpy ( path, &(rpc->u.reply.data[2]), retries + 1 );
356
-					path[retries] = 0;
357
-				}
358
-				return 0;
359
-			}
360
-		}
361
-	}
362
-	return -1;
363
-}
364
-/**************************************************************************
365
-NFS_LOOKUP - Lookup Pathname
366
-**************************************************************************/
367
-static int nfs_lookup(struct sockaddr_in *server, char *fh, char *path, char *nfh,
368
-	int sport)
369
-{
370
-	struct rpc_t buf, *rpc;
371
-	unsigned long id;
372
-	long *p;
373
-	int retries;
374
-	int pathlen = strlen(path);
375
-
376
-	id = rpc_id++;
377
-	buf.u.call.id = htonl(id);
378
-	buf.u.call.type = htonl(MSG_CALL);
379
-	buf.u.call.rpcvers = htonl(2);	/* use RPC version 2 */
380
-	buf.u.call.prog = htonl(PROG_NFS);
381
-	buf.u.call.vers = htonl(2);	/* nfsd is version 2 */
382
-	buf.u.call.proc = htonl(NFS_LOOKUP);
383
-	p = rpc_add_credentials((long *)buf.u.call.data);
384
-	memcpy(p, fh, NFS_FHSIZE);
385
-	p += (NFS_FHSIZE / 4);
386
-	*p++ = htonl(pathlen);
387
-	if (pathlen & 3) {
388
-		*(p + pathlen / 4) = 0;	/* add zero padding */
389
-	}
390
-	memcpy(p, path, pathlen);
391
-	p += (pathlen + 3) / 4;
392
-	for (retries = 0; retries < MAX_RPC_RETRIES; retries++) {
393
-		long timeout = rfc2131_sleep_interval(TIMEOUT, retries);
394
-		udp_transmit(server->sin_addr.s_addr, sport, server->sin_port,
395
-			(char *)p - (char *)&buf, &buf);
396
-		if (await_reply(await_rpc, sport, &id, timeout)) {
397
-			rpc = (struct rpc_t *)&nic.packet[ETH_HLEN];
398
-			if (rpc->u.reply.rstatus || rpc->u.reply.verifier ||
399
-			    rpc->u.reply.astatus || rpc->u.reply.data[0]) {
400
-				rpc_printerror(rpc);
401
-				if (rpc->u.reply.rstatus) {
402
-					/* RPC failed, no verifier, data[0] */
403
-					return -9999;
404
-				}
405
-				if (rpc->u.reply.astatus) {
406
-					/* RPC couldn't decode parameters */
407
-					return -9998;
408
-				}
409
-				return -ntohl(rpc->u.reply.data[0]);
410
-			} else {
411
-				memcpy(nfh, rpc->u.reply.data + 1, NFS_FHSIZE);
412
-				return 0;
413
-			}
414
-		}
415
-	}
416
-	return -1;
417
-}
418
-
419
-/**************************************************************************
420
-NFS_READ - Read File on NFS Server
421
-**************************************************************************/
422
-static int nfs_read(struct sockaddr_in *server, char *fh, int offset, int len,
423
-		    int sport)
424
-{
425
-	struct rpc_t buf, *rpc;
426
-	unsigned long id;
427
-	int retries;
428
-	long *p;
429
-
430
-	static int tokens=0;
431
-	/*
432
-	 * Try to implement something similar to a window protocol in
433
-	 * terms of response to losses. On successful receive, increment
434
-	 * the number of tokens by 1 (cap at 256). On failure, halve it.
435
-	 * When the number of tokens is >= 2, use a very short timeout.
436
-	 */
437
-
438
-	id = rpc_id++;
439
-	buf.u.call.id = htonl(id);
440
-	buf.u.call.type = htonl(MSG_CALL);
441
-	buf.u.call.rpcvers = htonl(2);	/* use RPC version 2 */
442
-	buf.u.call.prog = htonl(PROG_NFS);
443
-	buf.u.call.vers = htonl(2);	/* nfsd is version 2 */
444
-	buf.u.call.proc = htonl(NFS_READ);
445
-	p = rpc_add_credentials((long *)buf.u.call.data);
446
-	memcpy(p, fh, NFS_FHSIZE);
447
-	p += NFS_FHSIZE / 4;
448
-	*p++ = htonl(offset);
449
-	*p++ = htonl(len);
450
-	*p++ = 0;		/* unused parameter */
451
-	for (retries = 0; retries < MAX_RPC_RETRIES; retries++) {
452
-		long timeout = rfc2131_sleep_interval(TIMEOUT, retries);
453
-		if (tokens >= 2)
454
-			timeout = TICKS_PER_SEC/2;
455
-
456
-		udp_transmit(server->sin_addr.s_addr, sport, server->sin_port,
457
-			(char *)p - (char *)&buf, &buf);
458
-		if (await_reply(await_rpc, sport, &id, timeout)) {
459
-			if (tokens < 256)
460
-				tokens++;
461
-			rpc = (struct rpc_t *)&nic.packet[ETH_HLEN];
462
-			if (rpc->u.reply.rstatus || rpc->u.reply.verifier ||
463
-			    rpc->u.reply.astatus || rpc->u.reply.data[0]) {
464
-				rpc_printerror(rpc);
465
-				if (rpc->u.reply.rstatus) {
466
-					/* RPC failed, no verifier, data[0] */
467
-					return -9999;
468
-				}
469
-				if (rpc->u.reply.astatus) {
470
-					/* RPC couldn't decode parameters */
471
-					return -9998;
472
-				}
473
-				return -ntohl(rpc->u.reply.data[0]);
474
-			} else {
475
-				return 0;
476
-			}
477
-		} else
478
-			tokens >>= 1;
479
-	}
480
-	return -1;
481
-}
482
-
483
-/**************************************************************************
484
-NFS - Download extended BOOTP data, or kernel image from NFS server
485
-**************************************************************************/
486
-static int nfs ( char *url __unused, struct sockaddr_in *server,
487
-		 char *name, struct buffer *buffer ) {
488
-	static int recursion = 0;
489
-	int sport;
490
-	int err, namelen = strlen(name);
491
-	char dirname[300], *fname;
492
-	char dirfh[NFS_FHSIZE];		/* file handle of directory */
493
-	char filefh[NFS_FHSIZE];	/* file handle of kernel image */
494
-	int rlen, size, offs, len;
495
-	struct rpc_t *rpc;
496
-
497
-	sport = oport++;
498
-	if (oport > START_OPORT+OPORT_SWEEP) {
499
-		oport = START_OPORT;
500
-	}
501
-
502
-	mount_server.sin_addr = nfs_server.sin_addr = server->sin_addr;
503
-	mount_server.sin_port = rpc_lookup(server, PROG_MOUNT, 1, sport);
504
-	if ( ! mount_server.sin_port ) {
505
-		DBG ( "Cannot get mount port from %s:%d\n",
506
-		      inet_ntoa ( server->sin_addr ), server->sin_port );
507
-		return 0;
508
-	}
509
-	nfs_server.sin_port = rpc_lookup(server, PROG_NFS, 2, sport);
510
-	if ( ! mount_server.sin_port ) {
511
-		DBG ( "Cannot get nfs port from %s:%d\n",
512
-		      inet_ntoa ( server->sin_addr ), server->sin_port );
513
-		return 0;
514
-	}
515
-
516
-	if ( name != dirname ) {
517
-		memcpy(dirname, name, namelen + 1);
518
-	}
519
-	recursion = 0;
520
-nfssymlink:
521
-	if ( recursion > NFS_MAXLINKDEPTH ) {
522
-		DBG ( "\nRecursion: More than %d symlinks followed. Abort.\n",
523
-		      NFS_MAXLINKDEPTH );
524
-		return	0;
525
-	}
526
-	recursion++;
527
-	fname = dirname + (namelen - 1);
528
-	while (fname >= dirname) {
529
-		if (*fname == '/') {
530
-			*fname = '\0';
531
-			fname++;
532
-			break;
533
-		}
534
-		fname--;
535
-	}
536
-	if (fname < dirname) {
537
-		DBG("can't parse file name %s\n", name);
538
-		return 0;
539
-	}
540
-
541
-	err = nfs_mount(&mount_server, dirname, dirfh, sport);
542
-	if (err) {
543
-		DBG("mounting %s: ", dirname);
544
-		nfs_printerror(err);
545
-		/* just to be sure... */
546
-		nfs_reset();
547
-		return 0;
548
-	}
549
-
550
-	err = nfs_lookup(&nfs_server, dirfh, fname, filefh, sport);
551
-	if (err) {
552
-		DBG("looking up %s: ", fname);
553
-		nfs_printerror(err);
554
-		nfs_reset();
555
-		return 0;
556
-	}
557
-
558
-	offs = 0;
559
-	size = -1;	/* will be set properly with the first reply */
560
-	len = NFS_READ_SIZE;	/* first request is always full size */
561
-	do {
562
-		err = nfs_read(&nfs_server, filefh, offs, len, sport);
563
-                if ((err <= -NFSERR_ISDIR)&&(err >= -NFSERR_INVAL) && (offs == 0)) {
564
-			// An error occured. NFS servers tend to sending
565
-			// errors 21 / 22 when symlink instead of real file
566
-			// is requested. So check if it's a symlink!
567
-			if ( nfs_readlink(&nfs_server, dirfh, dirname,
568
-					  filefh, sport) == 0 ) {
569
-				printf("\nLoading symlink:%s ..",dirname);
570
-				goto nfssymlink;
571
-			}
572
-			nfs_printerror(err);
573
-			nfs_reset();
574
-			return 0;
575
-		}
576
-		if (err) {
577
-			printf("\nError reading at offset %d: ", offs);
578
-			nfs_printerror(err);
579
-			nfs_reset();
580
-			return 0;
581
-		}
582
-
583
-		rpc = (struct rpc_t *)&nic.packet[ETH_HLEN];
584
-
585
-		/* size must be found out early to allow EOF detection */
586
-		if (size == -1) {
587
-			size = ntohl(rpc->u.reply.data[6]);
588
-		}
589
-		rlen = ntohl(rpc->u.reply.data[18]);
590
-		if (rlen > len) {
591
-			rlen = len;	/* shouldn't happen...  */
592
-		}
593
-
594
-		if ( ! fill_buffer ( buffer, &rpc->u.reply.data[19],
595
-				     offs, rlen ) ) {
596
-			nfs_reset();
597
-			return 0;
598
-		}
599
-
600
-		offs += rlen;
601
-		/* last request is done with matching requested read size */
602
-		if (size-offs < NFS_READ_SIZE) {
603
-			len = size-offs;
604
-		}
605
-	} while (len != 0);
606
-	/* len == 0 means that all the file has been read */
607
-	return 1;
608
-}
609
-
610
-struct protocol nfs_protocol __protocol = {
611
-	.name = "nfs",
612
-	.default_port = SUNRPC_PORT,
613
-	.load = nfs,
614
-};
615
-
616
-#endif

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