diff options
Diffstat (limited to 'nfsd/loop.c')
-rw-r--r-- | nfsd/loop.c | 326 |
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); } } |