aboutsummaryrefslogtreecommitdiff
path: root/nfsd/loop.c
diff options
context:
space:
mode:
Diffstat (limited to 'nfsd/loop.c')
-rw-r--r--nfsd/loop.c326
1 files changed, 158 insertions, 168 deletions
diff --git a/nfsd/loop.c b/nfsd/loop.c
index 3520e1da..bfec5e5a 100644
--- a/nfsd/loop.c
+++ b/nfsd/loop.c
@@ -1,5 +1,5 @@
-/*
- Copyright (C) 1996 Free Software Foundation, Inc.
+/* loop.c - Main server loop for nfs server.
+ Copyright (C) 1996,98,2002,2006 Free Software Foundation, Inc.
Written by Michael I. Bushnell, p/BSG.
This file is part of the GNU Hurd.
@@ -24,7 +24,7 @@
#include "nfsd.h"
#include <rpc/pmap_prot.h>
-#include "../nfs/rpcsvc/mount.h"
+#include "../nfs/mount.h"
#undef TRUE
#undef FALSE
@@ -36,7 +36,7 @@
#undef malloc
void
-server_loop ()
+server_loop (int fd)
{
char buf[MAXIOSIZE];
int xid;
@@ -52,182 +52,172 @@ server_loop ()
struct idspec *cred;
struct cache_handle *c, fakec;
error_t err;
- size_t addrlen;
- fd_set readfds;
- int maxfd;
- int i;
- int *errloc;
-
- bzero (&fakec, sizeof (struct cache_handle));
-
- if (main_udp_socket > pmap_udp_socket)
- maxfd = main_udp_socket;
- else
- maxfd = pmap_udp_socket;
-
+ socklen_t addrlen;
+ int cc;
+
+ memset (&fakec, 0, sizeof (struct cache_handle));
+
for (;;)
{
- FD_ZERO (&readfds);
- FD_SET (main_udp_socket, &readfds);
- FD_SET (pmap_udp_socket, &readfds);
- select (maxfd, &readfds, 0, 0, 0);
-
- for (i = main_udp_socket;
- i != -1;
- i = (i == main_udp_socket ? pmap_udp_socket : -1))
+ p = (int *) buf;
+ proc = 0;
+ addrlen = sizeof (struct sockaddr_in);
+ cc = recvfrom (fd, buf, MAXIOSIZE, 0, &sender, &addrlen);
+ if (cc == -1)
+ continue; /* Ignore errors. */
+ xid = *(p++);
+
+ /* Ignore things that aren't proper RPCs. */
+ if (ntohl (*p) != CALL)
+ continue;
+ p++;
+
+ cr = check_cached_replies (xid, &sender);
+ if (cr->data)
+ /* This transacation has already completed. */
+ goto repost_reply;
+
+ r = (int *) (rbuf = malloc (MAXIOSIZE));
+
+ if (ntohl (*p) != RPC_MSG_VERSION)
{
- if (!FD_ISSET (i, &readfds))
- continue;
-
- p = (int *) buf;
- proc = 0;
- addrlen = sizeof (struct sockaddr_in);
- recvfrom (i, buf, MAXIOSIZE, 0, &sender, &addrlen);
- xid = *p++;
-
- /* Ignore things that aren't proper RPCs. */
- if (ntohl (*p++) != CALL)
- continue;
-
- cr = check_cached_replies (xid, &sender);
- if (cr->data)
- /* This transacation has already completed */
- goto repost_reply;
-
- r = (int *) rbuf = malloc (MAXIOSIZE);
-
- if (ntohl (*p++) != RPC_MSG_VERSION)
- {
- /* Reject RPC */
- *r++ = xid;
- *r++ = htonl (REPLY);
- *r++ = htonl (MSG_DENIED);
- *r++ = htonl (RPC_MISMATCH);
- *r++ = htonl (RPC_MSG_VERSION);
- *r++ = htonl (RPC_MSG_VERSION);
- goto send_reply;
- }
-
- program = ntohl (*p++);
- switch (program)
- {
- case MOUNTPROG:
- version = MOUNTVERS;
- table = &mounttable;
- break;
-
- case NFS_PROGRAM:
- version = NFS_VERSION;
- table = &nfstable;
- break;
-
- case PMAPPROG:
- version = PMAPVERS;
- table = &pmaptable;
- break;
-
- default:
- /* Program unavailable */
- *r++ = xid;
- *r++ = htonl (REPLY);
- *r++ = htonl (MSG_ACCEPTED);
- *r++ = htonl (AUTH_NULL);
- *r++ = htonl (0);
- *r++ = htonl (PROG_UNAVAIL);
- goto send_reply;
- }
-
- if (ntohl (*p++) != version)
- {
- /* Program mismatch */
- *r++ = xid;
- *r++ = htonl (REPLY);
- *r++ = htonl (MSG_ACCEPTED);
- *r++ = htonl (AUTH_NULL);
- *r++ = htonl (0);
- *r++ = htonl (PROG_MISMATCH);
- *r++ = htonl (version);
- *r++ = htonl (version);
- goto send_reply;
- }
-
- procedure = htonl (*p++);
- if (procedure < table->min
- || procedure > table->max
- || table->procs[procedure - table->min].func == 0)
- {
- /* Procedure unavailable */
- *r++ = xid;
- *r++ = htonl (REPLY);
- *r++ = htonl (MSG_ACCEPTED);
- *r++ = htonl (AUTH_NULL);
- *r++ = htonl (0);
- *r++ = htonl (PROC_UNAVAIL);
- *r++ = htonl (table->min);
- *r++ = htonl (table->max);
- goto send_reply;
- }
- proc = &table->procs[procedure - table->min];
-
- p = process_cred (p, &cred); /* auth */
- p = skip_cred (p); /* verf */
-
- if (proc->need_handle)
- p = lookup_cache_handle (p, &c, cred);
- else
- {
- fakec.ids = cred;
- c = &fakec;
- }
-
- if (proc->alloc_reply)
- {
- size_t amt;
- amt = (*proc->alloc_reply) (p) + 256;
- if (amt > MAXIOSIZE)
- {
- free (rbuf);
- r = (int *) rbuf = malloc (amt);
- }
- }
+ /* Reject RPC. */
+ *(r++) = xid;
+ *(r++) = htonl (REPLY);
+ *(r++) = htonl (MSG_DENIED);
+ *(r++) = htonl (RPC_MISMATCH);
+ *(r++) = htonl (RPC_MSG_VERSION);
+ *(r++) = htonl (RPC_MSG_VERSION);
+ goto send_reply;
+ }
+ p++;
+
+ program = ntohl (*p);
+ p++;
+ switch (program)
+ {
+ case MOUNTPROG:
+ version = MOUNTVERS;
+ table = &mounttable;
+ break;
+
+ case NFS_PROGRAM:
+ version = NFS_VERSION;
+ table = &nfs2table;
+ break;
+
+ case PMAPPROG:
+ version = PMAPVERS;
+ table = &pmaptable;
+ break;
+
+ default:
+ /* Program unavailable. */
+ *(r++) = xid;
+ *(r++) = htonl (REPLY);
+ *(r++) = htonl (MSG_ACCEPTED);
+ *(r++) = htonl (AUTH_NULL);
+ *(r++) = htonl (0);
+ *(r++) = htonl (PROG_UNAVAIL);
+ goto send_reply;
+ }
- /* Fill in beginning of reply */
- *r++ = xid;
- *r++ = htonl (REPLY);
- *r++ = htonl (MSG_ACCEPTED);
- *r++ = htonl (AUTH_NULL);
- *r++ = htonl (0);
- *r++ = htonl (SUCCESS);
- if (proc->process_error)
+ if (ntohl (*p) != version)
+ {
+ /* Program mismatch. */
+ *(r++) = xid;
+ *(r++) = htonl (REPLY);
+ *(r++) = htonl (MSG_ACCEPTED);
+ *(r++) = htonl (AUTH_NULL);
+ *(r++) = htonl (0);
+ *(r++) = htonl (PROG_MISMATCH);
+ *(r++) = htonl (version);
+ *(r++) = htonl (version);
+ goto send_reply;
+ }
+ p++;
+
+ procedure = htonl (*p);
+ p++;
+ if (procedure < table->min
+ || procedure > table->max
+ || table->procs[procedure - table->min].func == 0)
+ {
+ /* Procedure unavailable. */
+ *(r++) = xid;
+ *(r++) = htonl (REPLY);
+ *(r++) = htonl (MSG_ACCEPTED);
+ *(r++) = htonl (AUTH_NULL);
+ *(r++) = htonl (0);
+ *(r++) = htonl (PROC_UNAVAIL);
+ *(r++) = htonl (table->min);
+ *(r++) = htonl (table->max);
+ goto send_reply;
+ }
+ proc = &table->procs[procedure - table->min];
+
+ p = process_cred (p, &cred);
+
+ if (proc->need_handle)
+ p = lookup_cache_handle (p, &c, cred);
+ else
+ {
+ fakec.ids = cred;
+ c = &fakec;
+ }
+
+ if (proc->alloc_reply)
+ {
+ size_t amt;
+ amt = (*proc->alloc_reply) (p, version) + 256;
+ if (amt > MAXIOSIZE)
{
- /* Assume success for now and patch it later if necessary */
- errloc = r;
- *r++ = htonl (0);
+ free (rbuf);
+ r = (int *) (rbuf = malloc (amt));
}
+ }
+ /* Fill in beginning of reply. */
+ *(r++) = xid;
+ *(r++) = htonl (REPLY);
+ *(r++) = htonl (MSG_ACCEPTED);
+ *(r++) = htonl (AUTH_NULL);
+ *(r++) = htonl (0);
+ *(r++) = htonl (SUCCESS);
+ if (!proc->process_error)
+ /* The function does its own error processing, and we ignore
+ its return value. */
+ (void) (*proc->func) (c, p, &r, version);
+ else
+ {
if (c)
- err = (*proc->func) (c, p, &r);
- else
- err = ESTALE;
-
- if (proc->process_error && err)
{
- r = errloc;
- *r++ = htonl (nfs_error_trans (err));
+ /* Assume success for now and patch it later if necessary. */
+ int *errloc = r;
+ *(r++) = htonl (0);
+ /* Call processing function, its output after error code. */
+ err = (*proc->func) (c, p, &r, version);
+ if (err)
+ {
+ r = errloc; /* Back up, patch error code, discard rest. */
+ *(r++) = htonl (nfs_error_trans (err, version));
+ }
}
+ else
+ *(r++) = htonl (nfs_error_trans (ESTALE, version));
+ }
- cred_rele (cred);
- if (c != &fakec)
- cache_handle_rele (c);
+ cred_rele (cred);
+ if (c && c != &fakec)
+ cache_handle_rele (c);
- send_reply:
- cr->data = rbuf;
- cr->len = (char *)r - rbuf;
+ send_reply:
+ cr->data = rbuf;
+ cr->len = (char *)r - rbuf;
- repost_reply:
- sendto (i, cr->data, cr->len, 0,
- (struct sockaddr *)&sender, addrlen);
- release_cached_reply (cr);
- }
+ repost_reply:
+ sendto (fd, cr->data, cr->len, 0,
+ (struct sockaddr *) &sender, addrlen);
+ release_cached_reply (cr);
}
}