home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 13 / MA_Cover_13.bin / source / c / nfsd / src / service_nfsd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-11-29  |  5.9 KB  |  215 lines

  1. /*  Receives, decodes the headers and delegates incoming RPC packets
  2.  
  3.     ©1999 Joseph Walton
  4.  
  5.     This software is distributed under the terms of the GNU General Public
  6.     License; either version 2 of the License, or (at your option) any
  7.     later version.
  8. */
  9.  
  10. #include "rpc.h"
  11. #include "nfs.h"
  12. #include "mount.h"
  13. #include "pcnfsd.h"
  14.  
  15. #include "nfsd.h"
  16. #include "memory.h"
  17. #include "handle_list.h"
  18. #include "nfs_utils.h"
  19.  
  20. #include <stdio.h>
  21. #include <sys/socket.h>
  22. #include <netinet/in.h>
  23.  
  24. #include <proto/exec.h>
  25. #include <proto/dos.h>
  26. #include <proto/socket.h>
  27. #include <proto/timer.h>
  28.  
  29. extern BYTE *send_buffer, *recv_buffer; /* memory.c */
  30.  
  31. int handlePacket(int32 *ptr, int32 *limit, struct sockaddr_in *from);
  32. int pcnfsd_procedure(struct Call *call, int32 *ptr, int32 *limit,
  33.     int32 *rptr, int32 *rlimit);
  34.  
  35. void service(int s)
  36. {
  37.     struct sockaddr_in remote_sa;
  38.     int l, addr_len;
  39.     struct timeval timeout;
  40.     struct timeval last_flushed;
  41.     BOOL check_handles_pending = TRUE;
  42.  
  43.     fd_set fdset;
  44.  
  45.     GetSysTime(&last_flushed);
  46.  
  47.     while (TRUE) {
  48.         FD_ZERO(&fdset);
  49.         FD_SET(s, &fdset);
  50.  
  51.         if (check_handles_pending) {
  52.             DEBUG(puts("Waiting for a request with a timeout"));
  53.             timeout.tv_secs = FLUSH_HANDLES_EVERY;
  54.             timeout.tv_micro = 0;
  55.             l = WaitSelect(FD_SETSIZE, &fdset, NULL, NULL, &timeout, NULL);
  56.         } else {
  57.             DEBUG(puts("Waiting for a request without timeout"));
  58.             l = WaitSelect(FD_SETSIZE, &fdset, NULL, NULL, NULL, NULL);
  59.         }
  60.  
  61.         if (l < 0) {
  62.             printSocketError("WaitSelect() failed");
  63.             break;
  64.         }
  65.  
  66.         if (l > 0) {
  67.             addr_len = sizeof(remote_sa);
  68.             l = recvfrom(s, (char *)recv_buffer, RECV_BUFFER_BYTES, 0, &remote_sa, &addr_len);
  69.  
  70.             if (l < 0) {
  71.                 printSocketError("recvfrom() failed");
  72.                 break;
  73.             }
  74.  
  75.             DEBUG(printf("Packet received: %d bytes\n", l));
  76.  
  77.             /* Round it down */
  78.             l -= (l % SINT32);
  79.  
  80.             if (addr_len == sizeof(remote_sa)) {
  81.                 int response_len =
  82.                     handlePacket((int32 *)recv_buffer, (int32 *)(recv_buffer + l), &remote_sa);
  83.                 if (response_len >= 0) {
  84.                     int res = sendto(s, (char *)send_buffer, response_len * SINT32, 0, &remote_sa, sizeof(remote_sa));
  85.                     DEBUG(printf("Response sent: %d bytes\n", res));
  86.                     if (res < 0) {
  87.                         printSocketError("Could not send");
  88.                     }
  89.                 }
  90.  
  91.                 /* That may have had some effect on the handle list */
  92.                 check_handles_pending = TRUE;
  93.             } else {
  94.                 printf("Unexpected address length - %d\n", addr_len);
  95.             }
  96.         }
  97.  
  98.         /* Keep a periodic check on wasted memory */
  99.         struct timeval time_now;
  100.         GetSysTime(&time_now);
  101.         SubTime(&time_now, &last_flushed);
  102.         if (time_now.tv_secs > FLUSH_HANDLES_EVERY) {
  103.             if (verbose) {
  104.                 puts("Flushing unused NFS handles...");
  105.             }
  106.             check_handles_pending = flush_handles();
  107.             GetSysTime(&last_flushed);
  108.         }
  109.     }
  110. }
  111.  
  112. static int handlePacket(int32 *ptr, int32 *limit, struct sockaddr_in *from)
  113. {
  114.     int32 id;
  115.     int l;
  116.  
  117.     struct Call call;
  118.  
  119.     int32 *rptr = send_buffer;
  120.     int32 *rlimit = rptr + (SEND_BUFFER_BYTES / SINT32);
  121.  
  122.     if ((limit - ptr) < 6)
  123.         return -1;
  124.  
  125.     call.c_hasBeenPrinted = FALSE;
  126.  
  127.     // Assignment of structures
  128.     call.c_from = *from;
  129.  
  130.     id = G_UINT(*ptr++);
  131.  
  132.     /* One could, in theory, keep track of IDs and the corresponding
  133.         responses for swift retransmissions of repeated requests.
  134.        This is not done here, as it would require a fairly complex
  135.         cache and a fair bit of memory management, and would only benefit
  136.         us if packets were getting regularly lost on the way to the client.
  137.     */
  138.  
  139.     if (G_ENUM(*ptr++) != CALL) { // This is a call?
  140.         // We should simply ignore this silently
  141.         return -1;
  142.     }
  143.  
  144.     if (G_UINT(*ptr++) != RPC_VERSION) {
  145.         /* Requires 6 int32s */
  146.         *rptr++ = P_UINT(id);
  147.         *rptr++ = P_ENUM(REPLY);
  148.         *rptr++ = P_ENUM(MSG_DENIED);
  149.         *rptr++ = P_ENUM(RPC_MISMATCH);
  150.         *rptr++ = P_UINT(RPC_VERSION);
  151.         *rptr++ = P_UINT(RPC_VERSION);
  152.  
  153.         return 6;
  154.     }
  155.  
  156.     call.c_program = G_UINT(*ptr++);
  157.     call.c_version = G_UINT(*ptr++);
  158.     call.c_procedure = G_UINT(*ptr++);
  159.  
  160. //    printf("Program: %d, Version: %d, Procedure: %d\n", call.c_program,
  161. //        call.c_version, call.c_procedure);
  162.  
  163.     /* Authorisation */
  164.     ptr = readAuth(ptr, limit, &call.c_auth);
  165.     if (!ptr)
  166.         return -1;
  167.  
  168.     if ((limit - ptr) < 2)
  169.         return -1;
  170.  
  171.     /* We're not bothered about the verifier */
  172.     *ptr++;
  173.     l = G_UINT(*ptr++);
  174.     ptr += INT32S(l);
  175.     if (ptr >= limit) /* Check we've not overcommitted */
  176.         return -1;
  177.  
  178.     /* Check what authentication we got */
  179. /*    if (call.c_auth.isUnix) {
  180.         printf(" Name: %s, UID: %u GID: %u (%u secondary)\n",
  181.             call.c_auth.machineName, call.c_auth.uid,
  182.             call.c_auth.gid, call.c_auth.numGids);
  183.     } else {
  184.         puts("Non-UNIX authentication!");
  185. */
  186.         /* Ironically, we'd fail DES as 'too weak' */
  187. /*        *rptr++ = P_UINT(id);
  188.         *rptr++ = P_ENUM(REPLY);
  189.         *rptr++ = P_ENUM(MSG_DENIED);
  190.         *rptr++ = P_ENUM(AUTH_ERROR);
  191.         *rptr = P_ENUM(AUTH_TOOWEAK);
  192.         return 5;
  193.     }
  194. */
  195.     /* We've accepted the request */
  196.     rptr = PrepareAcceptedHeader(id, rptr);
  197.     // 5 int32s
  198.  
  199.     switch (call.c_program) {
  200.         case NFS_PROGRAM:
  201.             return nfs_procedure(&call, ptr, limit, rptr, rlimit);
  202.  
  203.         case MOUNT_PROGRAM:
  204.             return mount_procedure(&call, ptr, limit, rptr, rlimit);
  205.  
  206.         case PCNFSD_PROGRAM:
  207.             return pcnfsd_procedure(&call, ptr, limit, rptr, rlimit);
  208.  
  209.         default:
  210.             *rptr = P_ENUM(PROG_UNAVAIL);
  211.             return 6;
  212.     }
  213. }
  214.  
  215.