home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / n / tcpip / nfs-serv.1 / nfs-serv / nfs-server-2.1 / dispatch.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-10  |  6.5 KB  |  231 lines

  1. /*
  2.  * dispatch.c    This file contains the function dispatch table.
  3.  *
  4.  * Authors:    Donald J. Becker, <becker@super.org>
  5.  *        Rick Sladkey, <jrs@world.std.com>
  6.  *        Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
  7.  *        Olaf Kirch, <okir@monad.swb.de>
  8.  *
  9.  *        This software maybe be used for any purpose provided
  10.  *        the above copyright notice is retained.  It is supplied
  11.  *        as is, with no warranty expressed or implied.
  12.  */
  13.  
  14. #include "nfsd.h"
  15.  
  16. union argument_types     argument;
  17. union result_types    result;
  18. clnt_param        *cp;
  19.  
  20. extern int
  21.     nfsd_nfsproc_null_2(), nfsd_nfsproc_getattr_2(), nfsd_nfsproc_setattr_2(),
  22.     nfsd_nfsproc_root_2(), nfsd_nfsproc_lookup_2(), nfsd_nfsproc_readlink_2(),
  23.     nfsd_nfsproc_read_2(), nfsd_nfsproc_writecache_2(), nfsd_nfsproc_write_2(),
  24.     nfsd_nfsproc_create_2(), nfsd_nfsproc_remove_2(), nfsd_nfsproc_rename_2(),
  25.     nfsd_nfsproc_link_2(), nfsd_nfsproc_symlink_2(), nfsd_nfsproc_mkdir_2(),
  26.     nfsd_nfsproc_rmdir_2(), nfsd_nfsproc_readdir_2(), nfsd_nfsproc_statfs_2();
  27.  
  28. /* Allow the following to be over-ridden at compile time. */
  29.  
  30. #ifndef ROOT_UID
  31. #define ROOT_UID    0        /* Root user's ID. */
  32. #endif
  33.  
  34. #ifndef NOBODY_UID
  35. #define NOBODY_UID    ((uid_t) 65534)    /* The unprivileged user. */
  36. #endif
  37.  
  38. #ifndef NOBODY_GID
  39. #define NOBODY_GID    ((gid_t) 65534)    /* The unprivileged group. */
  40. #endif
  41.  
  42. uid_t fs_uid = 0;            /* Current effective IDs. */
  43. gid_t fs_gid = 0;
  44. GETGROUPS_T last_gids[NGRPS];        /* Current supplementary gids. */
  45. int last_len = -1;
  46.  
  47. /*
  48.  * This is a dispatch table to simplify error checking,
  49.  * and supply return attributes for NFS functions.
  50.  */
  51.  
  52. #ifdef __STDC__
  53. #define CONCAT(a,b)    a##b
  54. #define CONCAT3(a,b,c)    a##b##c
  55. #define STRING(a)    #a
  56. #else
  57. #define CONCAT(a,b)    a/**/b
  58. #define CONCAT3(a,b,c)    a/**/b/**/c
  59. #define STRING(a)    "a"
  60. #endif
  61.  
  62. #define table_ent(auth, ro, cred, res_type, arg_type, funct) {    \
  63.     auth, ro, cred, sizeof(res_type), sizeof(arg_type),    \
  64.     CONCAT(xdr_,res_type), CONCAT(xdr_,arg_type),        \
  65.     CONCAT3(nfsd_nfsproc_,funct,_2), STRING(funct),        \
  66.     CONCAT(pr_,arg_type)                    \
  67. }
  68.  
  69. #define nil    char
  70. #define xdr_nil    xdr_void
  71. #define pr_nil    pr_void
  72. #define pr_char    pr_void
  73.  
  74. struct dispatch_entry {
  75.     int    authenticate;        /* zero if op perm. to any    */
  76.     int    read_only;        /* zero if op perm. on RO FS    */
  77.     int    credentials;        /* zero if no creditials needed    */
  78.     int    res_size, arg_size;    /* sizeof the res/arg structs    */
  79.     bool_t    (*xdr_result)();
  80.     bool_t    (*xdr_argument)();
  81.     int    (*funct)();        /* function handler        */
  82.     char    *name;            /* name of function        */
  83.     char    *(*log_print)();    /* ptr to debug handler        */
  84. };
  85.  
  86. static struct dispatch_entry dtable[] = {
  87.     table_ent(0,0,0,nil,nil,null),            /* NULL */
  88.     table_ent(1,0,1,attrstat,nfs_fh,getattr),    /* GETATTR */
  89.     table_ent(1,1,1,attrstat,sattrargs,setattr),    /* SETATTR */
  90.     table_ent(0,0,0,nil,nil,root),            /* ROOT */
  91.     table_ent(1,0,1,diropres,diropargs,lookup),    /* LOOKUP */
  92.     table_ent(1,0,1,readlinkres,nfs_fh,readlink),    /* READLINK */
  93.     table_ent(1,0,1,readres,readargs,read),        /* READ */
  94.     table_ent(0,0,0,nil,nil,writecache),        /* WRITECACHE */
  95.     table_ent(1,1,1,attrstat,writeargs,write),    /* WRITE */
  96.     table_ent(1,1,1,diropres,createargs,create),    /* CREATE */
  97.     table_ent(1,1,1,nfsstat,diropargs,remove),    /* REMOVE */
  98.     table_ent(1,1,1,nfsstat,renameargs,rename),    /* RENAME */
  99.     table_ent(1,1,1,nfsstat,linkargs,link),        /* LINK */
  100.     table_ent(1,1,1,nfsstat,symlinkargs,symlink),    /* SYMLINK */
  101.     table_ent(1,1,1,diropres,createargs,mkdir),    /* MKDIR */
  102.     table_ent(1,1,1,nfsstat,diropargs,rmdir),    /* RMDIR */
  103.     table_ent(1,0,1,readdirres,readdirargs,readdir),/* READDIR */
  104.     table_ent(1,0,0,statfsres,nfs_fh,statfs),    /* STATFS */
  105. };
  106.  
  107. static _PRO( void set_ids, (struct svc_req *rqstp) );
  108.  
  109. void nfs_dispatch(rqstp, transp)
  110. struct svc_req *rqstp;
  111. SVCXPRT *transp;
  112. {
  113.     unsigned int proc_index = rqstp->rq_proc;
  114.     struct dispatch_entry *dent;
  115.  
  116.     if (proc_index >= (sizeof(dtable) / sizeof(dtable[0]))) {
  117.         svcerr_noproc(transp);
  118.         return;
  119.     }
  120.     dent = &dtable[proc_index];
  121.  
  122.     /* Initialize our variables for determining the attributes of
  123.        the file system in nfsd.c */
  124.     svc_rqstp = rqstp;
  125.     client_authenticate = dent->authenticate;
  126.  
  127.     memset(&argument, 0, dent->arg_size);
  128.     if (!svc_getargs(transp, dent->xdr_argument, &argument)) {
  129.         svcerr_decode(transp);
  130.         return;
  131.     }
  132.     /* Clear the result structure. */
  133.     memset(&result, 0, dent->res_size);
  134.  
  135.     /* Log the call. */
  136.     log_call(rqstp, dent->name, dent->log_print(&argument));
  137.  
  138. #ifdef READ_ONLY
  139.     /* Punt a write-type request if we are READ_ONLY. */
  140.     if (dent->read_only) {
  141.         result.nfsstat = NFSERR_ROFS;
  142.         goto report_status;
  143.     }
  144. #endif
  145.  
  146.     /* Establish the credentials and set the effective user IDs. */
  147.     if (dent->credentials)
  148.         set_ids(rqstp);
  149.  
  150.     /* Do the function call itself. */
  151.     result.nfsstat = (*dent->funct) (&argument);
  152.  
  153. #ifdef READ_ONLY
  154. report_status:
  155. #endif
  156.     dprintf(1, "result: %d\n", result.nfsstat);
  157.  
  158.     if (/* result.nfsstat >= 0 && */ /* nfsstat is unsigned? */
  159.       !svc_sendreply(transp, dent->xdr_result, (caddr_t) & result)) {
  160.         svcerr_systemerr(transp);
  161.     }
  162.     if (!svc_freeargs(transp, dent->xdr_argument, &argument)) {
  163.         dprintf(0, "unable to free RPC arguments, exiting\n");
  164.         exit(1);
  165.     }
  166. }
  167.  
  168. static void set_ids(rqstp)
  169. struct svc_req *rqstp;
  170. {
  171.     uid_t cred_uid;
  172.     gid_t cred_gid;
  173.     int cred_len;
  174.     GETGROUPS_T *cred_gids;
  175.     GETGROUPS_T fake_gid;
  176.  
  177.     if (rqstp->rq_cred.oa_flavor == AUTH_UNIX) {
  178.         struct authunix_parms *unix_cred;
  179.  
  180.         unix_cred = (struct authunix_parms *) rqstp->rq_clntcred;
  181.         cred_uid = unix_cred->aup_uid;
  182.         cred_gid = unix_cred->aup_gid;
  183.         cred_len = unix_cred->aup_len;
  184.         cred_gids = unix_cred->aup_gids;
  185.     } else {
  186.         cred_uid = NOBODY_UID;
  187.         cred_gid = NOBODY_GID;
  188.         /* Construct a list of one gid. */
  189.         cred_len = 1;
  190.         cred_gids = &fake_gid;
  191.         fake_gid = cred_gid;
  192.     }
  193.  
  194.     /* First, set the user ID. */
  195.     if (fs_uid != cred_uid) {
  196.         if (setfsuid(cred_uid) < 0)
  197.             dprintf(0, "Unable to setfsuid %d: %s\n",
  198.                 cred_uid, strerror(errno));
  199.         else {
  200.             fs_uid = cred_uid;
  201.         }
  202.     }
  203.  
  204.     /* Next, the group ID. */
  205.     if (fs_gid != cred_gid) {
  206.         if (setfsgid(cred_gid) < 0)
  207.             dprintf(0, "Unable to setfsgid %d: %s\n",
  208.                 cred_gid, strerror(errno));
  209.         else
  210.             fs_gid = cred_gid;
  211.     }
  212.  
  213. #ifdef HAVE_SETGROUPS
  214.     /* Finally, set the supplementary group IDs if possible. */
  215.     if (cred_len < 0 || cred_len > NGRPS)
  216.         dprintf(0, "Negative or huge cred_len: %d\n", cred_len);
  217.     else if (cred_len != last_len
  218.         || memcmp(cred_gids, last_gids, last_len*sizeof(gid_t))) {
  219.         if (setgroups(cred_len, cred_gids) < 0)
  220.             dprintf(0, "Unable to setgroups: %s\n",
  221.                 strerror(errno));
  222.         else {
  223.             memcpy(last_gids, cred_gids, cred_len*sizeof(gid_t));
  224.             last_len = cred_len;
  225.         }
  226.     }
  227. #endif /* HAVE_SETGROUPS */
  228.  
  229. }
  230.  
  231.