"Fossies" - the Fresh Open Source Software Archive

Member "glusterfs-6.9/xlators/nfs/server/src/acl3.c" (23 Apr 2020, 30669 Bytes) of package /linux/misc/glusterfs-6.9.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "acl3.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright (c) 2012-2013 Red Hat, Inc. <http://www.redhat.com>
    3  * This file is part of GlusterFS.
    4  *
    5  * This file is licensed to you under your choice of the GNU Lesser
    6  * General Public License, version 3 or any later version (LGPLv3 or
    7  * later), or the GNU General Public License, version 2 (GPLv2), in all
    8  * cases as published by the Free Software Foundation.
    9  */
   10 
   11 #include <glusterfs/defaults.h>
   12 #include "rpcsvc.h"
   13 #include <glusterfs/dict.h>
   14 #include <glusterfs/xlator.h>
   15 #include "nfs.h"
   16 #include <glusterfs/mem-pool.h>
   17 #include <glusterfs/logging.h>
   18 #include "nfs-fops.h"
   19 #include "nfs3.h"
   20 #include "nfs-mem-types.h"
   21 #include "nfs3-helpers.h"
   22 #include "nfs3-fh.h"
   23 #include "nfs-generics.h"
   24 #include "acl3.h"
   25 #include <glusterfs/byte-order.h>
   26 #include <glusterfs/compat-errno.h>
   27 #include "nfs-messages.h"
   28 
   29 static int
   30 acl3_nfs_acl_to_xattr(aclentry *ace, void *xattrbuf, int aclcount, int defacl);
   31 
   32 static int
   33 acl3_nfs_acl_from_xattr(aclentry *ace, void *xattrbuf, int bufsize, int defacl);
   34 
   35 typedef ssize_t (*acl3_serializer)(struct iovec outmsg, void *args);
   36 
   37 extern void
   38 nfs3_call_state_wipe(nfs3_call_state_t *cs);
   39 
   40 extern nfs3_call_state_t *
   41 nfs3_call_state_init(struct nfs3_state *s, rpcsvc_request_t *req, xlator_t *v);
   42 
   43 extern int
   44 nfs3_fh_validate(struct nfs3_fh *fh);
   45 
   46 extern void
   47 nfs3_stat_to_fattr3(struct iatt *buf, fattr3 *fa);
   48 
   49 #define acl3_validate_nfs3_state(request, state, status, label, retval)        \
   50     do {                                                                       \
   51         state = rpcsvc_request_program_private(request);                       \
   52         if (!state) {                                                          \
   53             gf_msg(GF_ACL, GF_LOG_ERROR, errno, NFS_MSG_STATE_MISSING,         \
   54                    "NFSv3 state "                                              \
   55                    "missing from RPC request");                                \
   56             rpcsvc_request_seterr(req, SYSTEM_ERR);                            \
   57             status = NFS3ERR_SERVERFAULT;                                      \
   58             goto label;                                                        \
   59         }                                                                      \
   60     } while (0);
   61 
   62 #define acl3_validate_gluster_fh(handle, status, errlabel)                     \
   63     do {                                                                       \
   64         if (!nfs3_fh_validate(handle)) {                                       \
   65             gf_msg(GF_ACL, GF_LOG_ERROR, EINVAL, NFS_MSG_BAD_HANDLE,           \
   66                    "Bad Handle");                                              \
   67             status = NFS3ERR_BADHANDLE;                                        \
   68             goto errlabel;                                                     \
   69         }                                                                      \
   70     } while (0)
   71 
   72 extern xlator_t *
   73 nfs3_fh_to_xlator(struct nfs3_state *nfs3, struct nfs3_fh *fh);
   74 
   75 #define acl3_map_fh_to_volume(nfs3state, handle, req, volume, status, label)   \
   76     do {                                                                       \
   77         char exportid[256], gfid[256];                                         \
   78         rpc_transport_t *trans = NULL;                                         \
   79         volume = nfs3_fh_to_xlator((nfs3state), handle);                       \
   80         if (!volume) {                                                         \
   81             gf_uuid_unparse(handle->exportid, exportid);                       \
   82             gf_uuid_unparse(handle->gfid, gfid);                               \
   83             trans = rpcsvc_request_transport(req);                             \
   84             gf_msg(GF_ACL, GF_LOG_ERROR, 0, NFS_MSG_FH_TO_VOL_FAIL,            \
   85                    "Failed to map "                                            \
   86                    "FH to vol: client=%s, exportid=%s, gfid=%s",               \
   87                    trans->peerinfo.identifier, exportid, gfid);                \
   88             gf_msg(GF_ACL, GF_LOG_ERROR, ESTALE, NFS_MSG_VOLUME_ERROR,         \
   89                    "Stale nfs client %s must be trying to "                    \
   90                    "connect to a deleted volume, please "                      \
   91                    "unmount it.",                                              \
   92                    trans->peerinfo.identifier);                                \
   93             status = NFS3ERR_STALE;                                            \
   94             goto label;                                                        \
   95         } else {                                                               \
   96             gf_msg_trace(GF_ACL, 0, "FH to Volume: %s", volume->name);         \
   97             rpcsvc_request_set_private(req, volume);                           \
   98         }                                                                      \
   99     } while (0);
  100 
  101 #define acl3_volume_started_check(nfs3state, vlm, rtval, erlbl)                \
  102     do {                                                                       \
  103         if ((!nfs_subvolume_started(nfs_state(nfs3state->nfsx), vlm))) {       \
  104             gf_msg(GF_ACL, GF_LOG_ERROR, 0, NFS_MSG_VOL_DISABLE,               \
  105                    "Volume is disabled: %s", vlm->name);                       \
  106             rtval = RPCSVC_ACTOR_IGNORE;                                       \
  107             goto erlbl;                                                        \
  108         }                                                                      \
  109     } while (0)
  110 
  111 #define acl3_check_fh_resolve_status(cst, nfstat, erlabl)                      \
  112     do {                                                                       \
  113         xlator_t *xlatorp = NULL;                                              \
  114         char buf[256], gfid[GF_UUID_BUF_SIZE];                                 \
  115         rpc_transport_t *trans = NULL;                                         \
  116         if ((cst)->resolve_ret < 0) {                                          \
  117             trans = rpcsvc_request_transport(cst->req);                        \
  118             xlatorp = nfs3_fh_to_xlator(cst->nfs3state, &cst->resolvefh);      \
  119             gf_uuid_unparse(cst->resolvefh.gfid, gfid);                        \
  120             snprintf(buf, sizeof(buf), "(%s) %s : %s",                         \
  121                      trans->peerinfo.identifier,                               \
  122                      xlatorp ? xlatorp->name : "ERR", gfid);                   \
  123             gf_msg(GF_ACL, GF_LOG_ERROR, cst->resolve_errno,                   \
  124                    NFS_MSG_RESOLVE_FH_FAIL,                                    \
  125                    "Unable to resolve "                                        \
  126                    "FH: %s",                                                   \
  127                    buf);                                                       \
  128             nfstat = nfs3_errno_to_nfsstat3(cst->resolve_errno);               \
  129             goto erlabl;                                                       \
  130         }                                                                      \
  131     } while (0)
  132 
  133 #define acl3_handle_call_state_init(nfs3state, calls, rq, v, opstat, errlabel) \
  134     do {                                                                       \
  135         calls = nfs3_call_state_init((nfs3state), (rq), v);                    \
  136         if (!calls) {                                                          \
  137             gf_msg(GF_ACL, GF_LOG_ERROR, 0, NFS_MSG_INIT_CALL_STAT_FAIL,       \
  138                    "Failed to "                                                \
  139                    "init call state");                                         \
  140             opstat = NFS3ERR_SERVERFAULT;                                      \
  141             rpcsvc_request_seterr(req, SYSTEM_ERR);                            \
  142             goto errlabel;                                                     \
  143         }                                                                      \
  144     } while (0)
  145 
  146 int
  147 acl3svc_submit_reply(rpcsvc_request_t *req, void *arg, acl3_serializer sfunc)
  148 {
  149     struct iovec outmsg = {
  150         0,
  151     };
  152     struct iobuf *iob = NULL;
  153     struct nfs3_state *nfs3 = NULL;
  154     int ret = -1;
  155     ssize_t msglen = 0;
  156     struct iobref *iobref = NULL;
  157 
  158     if (!req)
  159         return -1;
  160 
  161     nfs3 = (struct nfs3_state *)rpcsvc_request_program_private(req);
  162     if (!nfs3) {
  163         gf_msg(GF_ACL, GF_LOG_ERROR, EINVAL, NFS_MSG_MNT_STATE_NOT_FOUND,
  164                "mount state not found");
  165         goto ret;
  166     }
  167 
  168     /* First, get the io buffer into which the reply in arg will
  169      * be serialized.
  170      */
  171     iob = iobuf_get(nfs3->iobpool);
  172     if (!iob) {
  173         gf_msg(GF_ACL, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY,
  174                "Failed to get iobuf");
  175         goto ret;
  176     }
  177 
  178     iobuf_to_iovec(iob, &outmsg);
  179     /* Use the given serializer to translate the give C structure in arg
  180      * to XDR format which will be written into the buffer in outmsg.
  181      */
  182     msglen = sfunc(outmsg, arg);
  183     if (msglen < 0) {
  184         gf_msg(GF_ACL, GF_LOG_ERROR, errno, NFS_MSG_ENCODE_MSG_FAIL,
  185                "Failed to encode message");
  186         goto ret;
  187     }
  188     outmsg.iov_len = msglen;
  189 
  190     iobref = iobref_new();
  191     if (iobref == NULL) {
  192         gf_msg(GF_ACL, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY,
  193                "Failed to get iobref");
  194         goto ret;
  195     }
  196 
  197     ret = iobref_add(iobref, iob);
  198     if (ret) {
  199         gf_msg(GF_ACL, GF_LOG_ERROR, ENOMEM, NFS_MSG_NO_MEMORY,
  200                "Failed to add iob to iobref");
  201         goto ret;
  202     }
  203 
  204     /* Then, submit the message for transmission. */
  205     ret = rpcsvc_submit_message(req, &outmsg, 1, NULL, 0, iobref);
  206     if (ret == -1) {
  207         gf_msg(GF_ACL, GF_LOG_ERROR, errno, NFS_MSG_REP_SUBMIT_FAIL,
  208                "Reply submission failed");
  209         goto ret;
  210     }
  211 
  212     ret = 0;
  213 ret:
  214     if (iob)
  215         iobuf_unref(iob);
  216     if (iobref)
  217         iobref_unref(iobref);
  218 
  219     return ret;
  220 }
  221 
  222 int
  223 acl3svc_null(rpcsvc_request_t *req)
  224 {
  225     struct iovec dummyvec = {
  226         0,
  227     };
  228 
  229     if (!req) {
  230         gf_msg(GF_ACL, GF_LOG_ERROR, EINVAL, NFS_MSG_INVALID_ENTRY,
  231                "Got NULL request!");
  232         return 0;
  233     }
  234     rpcsvc_submit_generic(req, &dummyvec, 1, NULL, 0, NULL);
  235     return 0;
  236 }
  237 
  238 int
  239 acl3_getacl_reply(rpcsvc_request_t *req, getaclreply *reply)
  240 {
  241     acl3svc_submit_reply(req, (void *)reply,
  242                          (acl3_serializer)xdr_serialize_getaclreply);
  243     return 0;
  244 }
  245 
  246 int
  247 acl3_setacl_reply(rpcsvc_request_t *req, setaclreply *reply)
  248 {
  249     acl3svc_submit_reply(req, (void *)reply,
  250                          (acl3_serializer)xdr_serialize_setaclreply);
  251     return 0;
  252 }
  253 
  254 /* acl3_getacl_cbk: fetch and decode the ACL in the POSIX_ACL_ACCESS_XATTR
  255  *
  256  * The POSIX_ACL_ACCESS_XATTR can be set on files and directories.
  257  */
  258 int
  259 acl3_getacl_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
  260                 int32_t op_ret, int32_t op_errno, dict_t *dict, dict_t *xdata)
  261 {
  262     nfsstat3 stat = NFS3ERR_SERVERFAULT;
  263     nfs3_call_state_t *cs = NULL;
  264     data_t *data = NULL;
  265     getaclreply *getaclreply = NULL;
  266     int aclcount = 0;
  267     int defacl = 1; /* DEFAULT ACL */
  268 
  269     if (!frame->local) {
  270         gf_msg(GF_ACL, GF_LOG_ERROR, EINVAL, NFS_MSG_INVALID_ENTRY,
  271                "Invalid argument, frame->local NULL");
  272         return -EINVAL;
  273     }
  274     cs = frame->local;
  275     getaclreply = &cs->args.getaclreply;
  276     if ((op_ret < 0) && (op_errno != ENODATA && op_errno != ENOATTR)) {
  277         stat = nfs3_cbk_errno_status(op_ret, op_errno);
  278         goto err;
  279     } else if (!dict) {
  280         /* no ACL has been set */
  281         stat = NFS3_OK;
  282         goto err;
  283     }
  284 
  285     getaclreply->aclentry.aclentry_val = cs->aclentry;
  286 
  287     /* getfacl: NFS USER ACL */
  288     data = dict_get(dict, POSIX_ACL_ACCESS_XATTR);
  289     if (data && data->data) {
  290         aclcount = acl3_nfs_acl_from_xattr(cs->aclentry, data->data, data->len,
  291                                            !defacl);
  292         if (aclcount < 0) {
  293             gf_msg(GF_ACL, GF_LOG_ERROR, aclcount, NFS_MSG_GET_USER_ACL_FAIL,
  294                    "Failed to get USER ACL");
  295             stat = nfs3_errno_to_nfsstat3(-aclcount);
  296             goto err;
  297         }
  298         getaclreply->aclcount = aclcount;
  299         getaclreply->aclentry.aclentry_len = aclcount;
  300     }
  301 
  302     acl3_getacl_reply(cs->req, getaclreply);
  303     nfs3_call_state_wipe(cs);
  304     return 0;
  305 
  306 err:
  307     if (getaclreply)
  308         getaclreply->status = stat;
  309     acl3_getacl_reply(cs->req, getaclreply);
  310     nfs3_call_state_wipe(cs);
  311     return 0;
  312 }
  313 
  314 /* acl3_default_getacl_cbk: fetch and decode the ACL set in the
  315  * POSIX_ACL_DEFAULT_XATTR xattr.
  316  *
  317  * The POSIX_ACL_DEFAULT_XATTR xattr is only set on directories, not on files.
  318  *
  319  * When done with POSIX_ACL_DEFAULT_XATTR, we also need to get and decode the
  320  * ACL that can be set in POSIX_ACL_DEFAULT_XATTR.
  321  */
  322 int
  323 acl3_default_getacl_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
  324                         int32_t op_ret, int32_t op_errno, dict_t *dict,
  325                         dict_t *xdata)
  326 {
  327     nfsstat3 stat = NFS3ERR_SERVERFAULT;
  328     nfs3_call_state_t *cs = NULL;
  329     data_t *data = NULL;
  330     getaclreply *getaclreply = NULL;
  331     int aclcount = 0;
  332     int defacl = 1; /* DEFAULT ACL */
  333     nfs_user_t nfu = {
  334         0,
  335     };
  336     int ret = -1;
  337 
  338     if (!frame->local) {
  339         gf_msg(GF_ACL, GF_LOG_ERROR, EINVAL, NFS_MSG_INVALID_ENTRY,
  340                "Invalid argument, frame->local NULL");
  341         return -EINVAL;
  342     }
  343     cs = frame->local;
  344     getaclreply = &cs->args.getaclreply;
  345     if ((op_ret < 0) && (op_errno != ENODATA && op_errno != ENOATTR)) {
  346         stat = nfs3_cbk_errno_status(op_ret, op_errno);
  347         goto err;
  348     } else if (!dict) {
  349         /* no ACL has been set */
  350         stat = NFS3_OK;
  351         goto err;
  352     }
  353 
  354     getaclreply->daclentry.daclentry_val = cs->daclentry;
  355 
  356     /* getfacl: NFS DEFAULT ACL */
  357     data = dict_get(dict, POSIX_ACL_DEFAULT_XATTR);
  358     if (data && data->data) {
  359         aclcount = acl3_nfs_acl_from_xattr(cs->daclentry, data->data, data->len,
  360                                            defacl);
  361         if (aclcount < 0) {
  362             gf_msg(GF_ACL, GF_LOG_ERROR, aclcount, NFS_MSG_GET_DEF_ACL_FAIL,
  363                    "Failed to get DEFAULT ACL");
  364             stat = nfs3_errno_to_nfsstat3(-aclcount);
  365             goto err;
  366         }
  367 
  368         getaclreply->daclcount = aclcount;
  369         getaclreply->daclentry.daclentry_len = aclcount;
  370     }
  371 
  372     getaclreply->attr_follows = TRUE;
  373     nfs_request_user_init(&nfu, cs->req);
  374     ret = nfs_getxattr(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
  375                        POSIX_ACL_ACCESS_XATTR, NULL, acl3_getacl_cbk, cs);
  376     if (ret < 0) {
  377         stat = nfs3_errno_to_nfsstat3(-ret);
  378         goto err;
  379     }
  380 
  381     return 0;
  382 
  383 err:
  384     if (getaclreply)
  385         getaclreply->status = stat;
  386     acl3_getacl_reply(cs->req, getaclreply);
  387     nfs3_call_state_wipe(cs);
  388     return 0;
  389 }
  390 
  391 int
  392 acl3_stat_cbk(call_frame_t *frame, void *cookie, xlator_t *this, int32_t op_ret,
  393               int32_t op_errno, struct iatt *buf, dict_t *xdata)
  394 {
  395     nfsstat3 stat = NFS3ERR_SERVERFAULT;
  396     nfs3_call_state_t *cs = NULL;
  397     getaclreply *getaclreply = NULL;
  398     int ret = -1;
  399     nfs_user_t nfu = {
  400         0,
  401     };
  402     uint64_t deviceid = 0;
  403 
  404     if (!frame->local) {
  405         gf_msg(GF_ACL, GF_LOG_ERROR, EINVAL, NFS_MSG_INVALID_ENTRY,
  406                "Invalid argument, frame->local NULL");
  407         return EINVAL;
  408     }
  409 
  410     cs = frame->local;
  411     getaclreply = &cs->args.getaclreply;
  412 
  413     if (op_ret == -1) {
  414         stat = nfs3_cbk_errno_status(op_ret, op_errno);
  415         goto err;
  416     }
  417 
  418     /* Fill the attrs before xattrs */
  419     getaclreply->attr_follows = TRUE;
  420     deviceid = nfs3_request_xlator_deviceid(cs->req);
  421     nfs3_map_deviceid_to_statdev(buf, deviceid);
  422     nfs3_stat_to_fattr3(buf, &(getaclreply->attr));
  423 
  424     nfs_request_user_init(&nfu, cs->req);
  425     if (buf->ia_type == IA_IFDIR) {
  426         ret = nfs_getxattr(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
  427                            POSIX_ACL_DEFAULT_XATTR, NULL,
  428                            acl3_default_getacl_cbk, cs);
  429     } else {
  430         ret = nfs_getxattr(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc,
  431                            POSIX_ACL_ACCESS_XATTR, NULL, acl3_getacl_cbk, cs);
  432     }
  433 
  434     if (ret < 0) {
  435         stat = nfs3_errno_to_nfsstat3(-ret);
  436         goto err;
  437     }
  438 
  439     return 0;
  440 err:
  441     getaclreply->status = stat;
  442     acl3_getacl_reply(cs->req, getaclreply);
  443     nfs3_call_state_wipe(cs);
  444     return 0;
  445 }
  446 
  447 int
  448 acl3_getacl_resume(void *carg)
  449 {
  450     int ret = -1;
  451     nfs3_call_state_t *cs = NULL;
  452     nfsstat3 stat = NFS3ERR_SERVERFAULT;
  453     nfs_user_t nfu = {
  454         0,
  455     };
  456 
  457     if (!carg)
  458         return ret;
  459 
  460     cs = (nfs3_call_state_t *)carg;
  461     acl3_check_fh_resolve_status(cs, stat, acl3err);
  462     nfs_request_user_init(&nfu, cs->req);
  463 
  464     ret = nfs_stat(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, acl3_stat_cbk,
  465                    cs);
  466     stat = -ret;
  467 acl3err:
  468     if (ret < 0) {
  469         gf_msg(GF_ACL, GF_LOG_ERROR, stat, NFS_MSG_OPEN_FAIL,
  470                "unable to open_and_resume");
  471         cs->args.getaclreply.status = nfs3_errno_to_nfsstat3(stat);
  472         acl3_getacl_reply(cs->req, &cs->args.getaclreply);
  473         nfs3_call_state_wipe(cs);
  474     }
  475 
  476     return ret;
  477 }
  478 
  479 int
  480 acl3svc_getacl(rpcsvc_request_t *req)
  481 {
  482     xlator_t *vol = NULL;
  483     struct nfs_state *nfs = NULL;
  484     nfs3_state_t *nfs3 = NULL;
  485     nfs3_call_state_t *cs = NULL;
  486     int ret = RPCSVC_ACTOR_ERROR;
  487     nfsstat3 stat = NFS3ERR_SERVERFAULT;
  488     struct nfs3_fh fh, *fhp = NULL;
  489     getaclargs getaclargs;
  490     getaclreply getaclreply;
  491 
  492     if (!req)
  493         return ret;
  494 
  495     acl3_validate_nfs3_state(req, nfs3, stat, rpcerr, ret);
  496     nfs = nfs_state(nfs3->nfsx);
  497     memset(&getaclargs, 0, sizeof(getaclargs));
  498     memset(&getaclreply, 0, sizeof(getaclreply));
  499     getaclargs.fh.n_bytes = (char *)&fh;
  500     if (xdr_to_getaclargs(req->msg[0], &getaclargs) <= 0) {
  501         gf_msg(GF_ACL, GF_LOG_ERROR, errno, NFS_MSG_ARGS_DECODE_ERROR,
  502                "Error decoding args");
  503         rpcsvc_request_seterr(req, GARBAGE_ARGS);
  504         goto rpcerr;
  505     }
  506 
  507     /* Validate ACL mask */
  508     if (getaclargs.mask & ~(NFS_ACL | NFS_ACLCNT | NFS_DFACL | NFS_DFACLCNT)) {
  509         stat = NFS3ERR_INVAL;
  510         goto acl3err;
  511     }
  512 
  513     fhp = &fh;
  514     acl3_validate_gluster_fh(&fh, stat, acl3err);
  515     acl3_map_fh_to_volume(nfs->nfs3state, fhp, req, vol, stat, acl3err);
  516     acl3_volume_started_check(nfs3, vol, ret, rpcerr);
  517     acl3_handle_call_state_init(nfs->nfs3state, cs, req, vol, stat, acl3err);
  518 
  519     cs->vol = vol;
  520     cs->args.getaclreply.mask = getaclargs.mask;
  521 
  522     ret = nfs3_fh_resolve_and_resume(cs, fhp, NULL, acl3_getacl_resume);
  523     stat = nfs3_errno_to_nfsstat3(-ret);
  524 
  525 acl3err:
  526     if (ret < 0) {
  527         gf_msg(GF_ACL, GF_LOG_ERROR, -ret, NFS_MSG_RESOLVE_ERROR,
  528                "unable to resolve and resume");
  529         getaclreply.status = stat;
  530         acl3_getacl_reply(req, &getaclreply);
  531         nfs3_call_state_wipe(cs);
  532         return 0;
  533     }
  534 
  535 rpcerr:
  536     return ret;
  537 }
  538 
  539 int
  540 acl3_setacl_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
  541                 int32_t op_ret, int32_t op_errno, dict_t *xdata)
  542 {
  543     nfs3_call_state_t *cs = NULL;
  544     cs = frame->local;
  545     if (op_ret < 0) {
  546         nfsstat3 status = nfs3_cbk_errno_status(op_ret, op_errno);
  547         cs->args.setaclreply.status = status;
  548     }
  549 
  550     acl3_setacl_reply(cs->req, &cs->args.setaclreply);
  551 
  552     nfs3_call_state_wipe(cs);
  553 
  554     return 0;
  555 }
  556 
  557 int
  558 acl3_setacl_resume(void *carg)
  559 {
  560     int ret = -1;
  561     nfs3_call_state_t *cs = NULL;
  562     nfsstat3 stat = NFS3ERR_SERVERFAULT;
  563     nfs_user_t nfu = {
  564         0,
  565     };
  566     dict_t *xattr = NULL;
  567 
  568     if (!carg)
  569         return ret;
  570     cs = (nfs3_call_state_t *)carg;
  571     acl3_check_fh_resolve_status(cs, stat, acl3err);
  572     nfs_request_user_init(&nfu, cs->req);
  573     xattr = dict_new();
  574     if (cs->aclcount)
  575         ret = dict_set_static_bin(xattr, POSIX_ACL_ACCESS_XATTR, cs->aclxattr,
  576                                   posix_acl_xattr_size(cs->aclcount));
  577     if (cs->daclcount)
  578         ret = dict_set_static_bin(xattr, POSIX_ACL_DEFAULT_XATTR, cs->daclxattr,
  579                                   posix_acl_xattr_size(cs->daclcount));
  580 
  581     ret = nfs_setxattr(cs->nfsx, cs->vol, &nfu, &cs->resolvedloc, xattr, 0,
  582                        NULL, acl3_setacl_cbk, cs);
  583     dict_unref(xattr);
  584 
  585 acl3err:
  586     if (ret < 0) {
  587         stat = -ret;
  588         gf_msg(GF_ACL, GF_LOG_ERROR, stat, NFS_MSG_OPEN_FAIL,
  589                "unable to open_and_resume");
  590         cs->args.setaclreply.status = nfs3_errno_to_nfsstat3(stat);
  591         acl3_setacl_reply(cs->req, &cs->args.setaclreply);
  592         nfs3_call_state_wipe(cs);
  593     }
  594 
  595     return ret;
  596 }
  597 
  598 int
  599 acl3svc_setacl(rpcsvc_request_t *req)
  600 {
  601     xlator_t *vol = NULL;
  602     struct nfs_state *nfs = NULL;
  603     nfs3_state_t *nfs3 = NULL;
  604     nfs3_call_state_t *cs = NULL;
  605     int ret = RPCSVC_ACTOR_ERROR;
  606     nfsstat3 stat = NFS3ERR_SERVERFAULT;
  607     struct nfs3_fh fh;
  608     struct nfs3_fh *fhp = NULL;
  609     setaclargs setaclargs;
  610     setaclreply setaclreply;
  611     aclentry *daclentry = NULL;
  612     aclentry *aclentry = NULL;
  613     int aclerrno = 0;
  614     int defacl = 1;
  615 
  616     if (!req)
  617         return ret;
  618     aclentry = GF_CALLOC(NFS_ACL_MAX_ENTRIES, sizeof(*aclentry), gf_nfs_mt_arr);
  619     if (!aclentry) {
  620         goto rpcerr;
  621     }
  622     daclentry = GF_CALLOC(NFS_ACL_MAX_ENTRIES, sizeof(*daclentry),
  623                           gf_nfs_mt_arr);
  624     if (!daclentry) {
  625         goto rpcerr;
  626     }
  627 
  628     acl3_validate_nfs3_state(req, nfs3, stat, rpcerr, ret);
  629     nfs = nfs_state(nfs3->nfsx);
  630     memset(&setaclargs, 0, sizeof(setaclargs));
  631     memset(&setaclreply, 0, sizeof(setaclreply));
  632     memset(&fh, 0, sizeof(fh));
  633     setaclargs.fh.n_bytes = (char *)&fh;
  634     setaclargs.aclentry.aclentry_val = aclentry;
  635     setaclargs.daclentry.daclentry_val = daclentry;
  636     if (xdr_to_setaclargs(req->msg[0], &setaclargs) <= 0) {
  637         gf_msg(GF_ACL, GF_LOG_ERROR, errno, NFS_MSG_ARGS_DECODE_ERROR,
  638                "Error decoding args");
  639         rpcsvc_request_seterr(req, GARBAGE_ARGS);
  640         goto rpcerr;
  641     }
  642 
  643     /* Validate ACL mask */
  644     if (setaclargs.mask & ~(NFS_ACL | NFS_ACLCNT | NFS_DFACL | NFS_DFACLCNT)) {
  645         stat = NFS3ERR_INVAL;
  646         goto acl3err;
  647     }
  648 
  649     fhp = &fh;
  650     acl3_validate_gluster_fh(fhp, stat, acl3err);
  651     acl3_map_fh_to_volume(nfs->nfs3state, fhp, req, vol, stat, acl3err);
  652     acl3_volume_started_check(nfs3, vol, ret, rpcerr);
  653     acl3_handle_call_state_init(nfs->nfs3state, cs, req, vol, stat, acl3err);
  654 
  655     cs->vol = vol;
  656     cs->aclcount = setaclargs.aclcount;
  657     cs->daclcount = setaclargs.daclcount;
  658 
  659     /* setfacl: NFS USER ACL */
  660     aclerrno = acl3_nfs_acl_to_xattr(aclentry, cs->aclxattr, cs->aclcount,
  661                                      !defacl);
  662     if (aclerrno < 0) {
  663         gf_msg(GF_ACL, GF_LOG_ERROR, -aclerrno, NFS_MSG_SET_USER_ACL_FAIL,
  664                "Failed to set USER ACL");
  665         stat = nfs3_errno_to_nfsstat3(-aclerrno);
  666         goto acl3err;
  667     }
  668 
  669     /* setfacl: NFS DEFAULT ACL */
  670     aclerrno = acl3_nfs_acl_to_xattr(daclentry, cs->daclxattr, cs->daclcount,
  671                                      defacl);
  672     if (aclerrno < 0) {
  673         gf_msg(GF_ACL, GF_LOG_ERROR, -aclerrno, NFS_MSG_SET_DEF_ACL_FAIL,
  674                "Failed to set DEFAULT ACL");
  675         stat = nfs3_errno_to_nfsstat3(-aclerrno);
  676         goto acl3err;
  677     }
  678 
  679     ret = nfs3_fh_resolve_and_resume(cs, fhp, NULL, acl3_setacl_resume);
  680     stat = nfs3_errno_to_nfsstat3(-ret);
  681 
  682 acl3err:
  683     if (ret < 0) {
  684         gf_msg(GF_ACL, GF_LOG_ERROR, -ret, NFS_MSG_RESOLVE_ERROR,
  685                "unable to resolve and resume");
  686         setaclreply.status = stat;
  687         acl3_setacl_reply(req, &setaclreply);
  688         nfs3_call_state_wipe(cs);
  689         GF_FREE(aclentry);
  690         GF_FREE(daclentry);
  691         return 0;
  692     }
  693 
  694 rpcerr:
  695     if (ret < 0)
  696         nfs3_call_state_wipe(cs);
  697     if (aclentry)
  698         GF_FREE(aclentry);
  699     if (daclentry)
  700         GF_FREE(daclentry);
  701     return ret;
  702 }
  703 
  704 rpcsvc_actor_t acl3svc_actors[ACL3_PROC_COUNT] = {
  705     {"NULL", ACL3_NULL, acl3svc_null, NULL, 0, DRC_NA},
  706     {"GETACL", ACL3_GETACL, acl3svc_getacl, NULL, 0, DRC_NA},
  707     {"SETACL", ACL3_SETACL, acl3svc_setacl, NULL, 0, DRC_NA},
  708 };
  709 
  710 rpcsvc_program_t acl3prog = {
  711     .progname = "ACL3",
  712     .prognum = ACL_PROGRAM,
  713     .progver = ACLV3_VERSION,
  714     .progport = GF_NFS3_PORT,
  715     .actors = acl3svc_actors,
  716     .numactors = ACL3_PROC_COUNT,
  717     .min_auth = AUTH_NULL,
  718 };
  719 
  720 rpcsvc_program_t *
  721 acl3svc_init(xlator_t *nfsx)
  722 {
  723     struct nfs3_state *ns = NULL;
  724     struct nfs_state *nfs = NULL;
  725     dict_t *options = NULL;
  726     int ret = -1;
  727     char *portstr = NULL;
  728     static gf_boolean_t acl3_inited = _gf_false;
  729 
  730     /* Already inited */
  731     if (acl3_inited)
  732         return &acl3prog;
  733 
  734     nfs = (struct nfs_state *)nfsx->private;
  735 
  736     ns = nfs->nfs3state;
  737     if (!ns) {
  738         gf_msg(GF_ACL, GF_LOG_ERROR, EINVAL, NFS_MSG_ACL_INIT_FAIL,
  739                "ACL3 init failed");
  740         goto err;
  741     }
  742     acl3prog.private = ns;
  743 
  744     options = dict_new();
  745 
  746     ret = gf_asprintf(&portstr, "%d", GF_ACL3_PORT);
  747     if (ret == -1)
  748         goto err;
  749 
  750     ret = dict_set_dynstr(options, "transport.socket.listen-port", portstr);
  751     if (ret == -1)
  752         goto err;
  753     ret = dict_set_str(options, "transport-type", "socket");
  754     if (ret == -1) {
  755         gf_msg(GF_ACL, GF_LOG_ERROR, errno, NFS_MSG_DICT_SET_FAILED,
  756                "dict_set_str error");
  757         goto err;
  758     }
  759 
  760     if (nfs->allow_insecure) {
  761         ret = dict_set_str(options, "rpc-auth-allow-insecure", "on");
  762         if (ret == -1) {
  763             gf_msg(GF_ACL, GF_LOG_ERROR, errno, NFS_MSG_DICT_SET_FAILED,
  764                    "dict_set_str error");
  765             goto err;
  766         }
  767         ret = dict_set_str(options, "rpc-auth.ports.insecure", "on");
  768         if (ret == -1) {
  769             gf_msg(GF_ACL, GF_LOG_ERROR, errno, NFS_MSG_DICT_SET_FAILED,
  770                    "dict_set_str error");
  771             goto err;
  772         }
  773     }
  774 
  775     ret = dict_set_str(options, "transport.address-family", "inet");
  776     if (ret == -1) {
  777         gf_msg(GF_ACL, GF_LOG_ERROR, errno, NFS_MSG_DICT_SET_FAILED,
  778                "dict_set_str error");
  779         goto err;
  780     }
  781 
  782     ret = rpcsvc_create_listeners(nfs->rpcsvc, options, "ACL");
  783     if (ret == -1) {
  784         gf_msg(GF_ACL, GF_LOG_ERROR, errno, NFS_MSG_LISTENERS_CREATE_FAIL,
  785                "Unable to create listeners");
  786         dict_unref(options);
  787         goto err;
  788     }
  789 
  790     acl3_inited = _gf_true;
  791     return &acl3prog;
  792 err:
  793     return NULL;
  794 }
  795 
  796 static int
  797 acl3_nfs_acl_to_xattr(aclentry *ace,  /* ACL entries to be read */
  798                       void *xattrbuf, /* XATTR buf to be populated */
  799                       int aclcount,   /* No of ACLs to be read */
  800                       int defacl)     /* 1 if DEFAULT ACL */
  801 {
  802     int idx = 0;
  803     posix_acl_xattr_header *xheader = NULL;
  804     posix_acl_xattr_entry *xentry = NULL;
  805 
  806     if ((!ace) || (!xattrbuf))
  807         return (-EINVAL);
  808 
  809     /* ACL count is ZERO, nothing to do */
  810     if (!aclcount)
  811         return (0);
  812 
  813     if ((aclcount < 0) || (aclcount > NFS_ACL_MAX_ENTRIES))
  814         return (-EINVAL);
  815 
  816     xheader = (posix_acl_xattr_header *)(xattrbuf);
  817     xentry = (posix_acl_xattr_entry *)(xheader + 1);
  818 
  819     /*
  820      * For "default ACL", NFSv3 handles the 'type' differently
  821      * i.e. by logical OR'ing 'type' with NFS_ACL_DEFAULT.
  822      * Which the backend File system does not understand and
  823      * that needs to be masked OFF.
  824      */
  825     xheader->version = POSIX_ACL_XATTR_VERSION;
  826 
  827     for (idx = 0; idx < aclcount; idx++) {
  828         xentry->tag = ace->type;
  829         if (defacl)
  830             xentry->tag &= ~NFS_ACL_DEFAULT;
  831         xentry->perm = ace->perm;
  832 
  833         switch (xentry->tag) {
  834             case POSIX_ACL_USER:
  835             case POSIX_ACL_GROUP:
  836                 if (xentry->perm & ~S_IRWXO)
  837                     return (-EINVAL);
  838                 xentry->id = ace->uid;
  839                 break;
  840             case POSIX_ACL_USER_OBJ:
  841             case POSIX_ACL_GROUP_OBJ:
  842             case POSIX_ACL_OTHER:
  843                 if (xentry->perm & ~S_IRWXO)
  844                     return (-EINVAL);
  845                 xentry->id = POSIX_ACL_UNDEFINED_ID;
  846                 break;
  847             case POSIX_ACL_MASK:
  848                 /* Solaris sometimes sets additional bits in
  849                  * the mask.
  850                  */
  851                 xentry->perm &= S_IRWXO;
  852                 xentry->id = POSIX_ACL_UNDEFINED_ID;
  853                 break;
  854             default:
  855                 return (-EINVAL);
  856         }
  857 
  858         xentry++;
  859         ace++;
  860     }
  861 
  862     /* SUCCESS */
  863     return (0);
  864 }
  865 
  866 static int
  867 acl3_nfs_acl_from_xattr(aclentry *ace,  /* ACL entries to be filled */
  868                         void *xattrbuf, /* XATTR buf to be read */
  869                         int bufsize,    /* Size of XATTR buffer */
  870                         int defacl)     /*  1 if DEFAULT ACL */
  871 {
  872     int idx = 0;
  873     ssize_t aclcount = 0;
  874     posix_acl_xattr_header *xheader = NULL;
  875     posix_acl_xattr_entry *xentry = NULL;
  876 
  877     if ((!xattrbuf) || (!ace))
  878         return (-EINVAL);
  879 
  880     aclcount = posix_acl_xattr_count(bufsize);
  881     if ((aclcount < 0) || (aclcount > NFS_ACL_MAX_ENTRIES))
  882         return (-EINVAL);
  883 
  884     xheader = (posix_acl_xattr_header *)(xattrbuf);
  885     xentry = (posix_acl_xattr_entry *)(xheader + 1);
  886 
  887     /* Check for supported POSIX ACL xattr version */
  888     if (xheader->version != POSIX_ACL_XATTR_VERSION)
  889         return (-ENOSYS);
  890 
  891     for (idx = 0; idx < (int)aclcount; idx++) {
  892         ace->type = xentry->tag;
  893         if (defacl) {
  894             /*
  895              * SET the NFS_ACL_DEFAULT flag for default
  896              * ACL which was masked OFF during setfacl().
  897              */
  898             ace->type |= NFS_ACL_DEFAULT;
  899         }
  900         ace->perm = (xentry->perm & S_IRWXO);
  901 
  902         switch (xentry->tag) {
  903             case POSIX_ACL_USER:
  904             case POSIX_ACL_GROUP:
  905                 ace->uid = xentry->id;
  906                 break;
  907             case POSIX_ACL_USER_OBJ:
  908             case POSIX_ACL_GROUP_OBJ:
  909             case POSIX_ACL_MASK:
  910             case POSIX_ACL_OTHER:
  911                 ace->uid = POSIX_ACL_UNDEFINED_ID;
  912                 break;
  913             default:
  914                 return (-EINVAL);
  915         }
  916 
  917         xentry++;
  918         ace++;
  919     }
  920 
  921     /* SUCCESS: ACL count */
  922     return aclcount;
  923 }