diff options
| author | krishna <krishna@gluster.com> | 2011-07-27 18:16:59 +0530 | 
|---|---|---|
| committer | Anand Avati <avati@gluster.com> | 2011-07-29 03:37:07 -0700 | 
| commit | 6c7a89321af50925fb53da378d996881a1907f31 (patch) | |
| tree | bfa27e593f6418879a13873c9db6f01676904c7c /rpc | |
| parent | 8b9cb1701f6365f7b4f5ed166f37020781f59467 (diff) | |
RPC unify code change
Change-Id: Ibe18a2a63fd023ac57652c4dfc8ac8a69d983b83
BUG: 3112
Signed-off-by: krishna <krishna@gluster.com>
Reviewed-on: http://review.gluster.com/116
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Amar Tumballi <amar@gluster.com>
Diffstat (limited to 'rpc')
| -rw-r--r-- | rpc/rpc-lib/src/rpc-clnt.c | 22 | ||||
| -rw-r--r-- | rpc/rpc-lib/src/rpc-common.c | 6 | ||||
| -rw-r--r-- | rpc/rpc-lib/src/rpc-transport.c | 16 | ||||
| -rw-r--r-- | rpc/rpc-lib/src/rpc-transport.h | 4 | ||||
| -rw-r--r-- | rpc/rpc-lib/src/rpcsvc-auth.c | 91 | ||||
| -rw-r--r-- | rpc/rpc-lib/src/rpcsvc-common.h | 2 | ||||
| -rw-r--r-- | rpc/rpc-lib/src/rpcsvc.c | 617 | ||||
| -rw-r--r-- | rpc/rpc-lib/src/rpcsvc.h | 25 | ||||
| -rw-r--r-- | rpc/rpc-lib/src/xdr-common.h | 2 | ||||
| -rw-r--r-- | rpc/rpc-transport/socket/src/socket.c | 89 | ||||
| -rw-r--r-- | rpc/rpc-transport/socket/src/socket.h | 3 | ||||
| -rw-r--r-- | rpc/xdr/src/Makefile.am | 6 | ||||
| -rw-r--r-- | rpc/xdr/src/msg-nfs3.c | 555 | ||||
| -rw-r--r-- | rpc/xdr/src/msg-nfs3.h | 186 | ||||
| -rw-r--r-- | rpc/xdr/src/xdr-generic.c | 36 | ||||
| -rw-r--r-- | rpc/xdr/src/xdr-generic.h | 11 | ||||
| -rw-r--r-- | rpc/xdr/src/xdr-nfs3.c | 1897 | ||||
| -rw-r--r-- | rpc/xdr/src/xdr-nfs3.h | 1206 | 
18 files changed, 4698 insertions, 76 deletions
diff --git a/rpc/rpc-lib/src/rpc-clnt.c b/rpc/rpc-lib/src/rpc-clnt.c index 819951c7e0d..09e676179d3 100644 --- a/rpc/rpc-lib/src/rpc-clnt.c +++ b/rpc/rpc-lib/src/rpc-clnt.c @@ -392,7 +392,8 @@ rpc_clnt_reconnect (void *trans_ptr)                          gf_log (trans->name, GF_LOG_TRACE,                                  "attempting reconnect"); -                        ret = rpc_transport_connect (trans, conn->config.remote_port); +                        ret = rpc_transport_connect (trans, +                                                     conn->config.remote_port);                          /* Every time there is a disconnection, processes                             should try to connect to 'glusterd' (ie, default                             port) or whichever port given as 'option remote-port' @@ -435,7 +436,8 @@ rpc_clnt_fill_request_info (struct rpc_clnt *clnt, rpc_request_info_t *info)          pthread_mutex_unlock (&clnt->conn.lock);          if (ret == -1) { -                gf_log (clnt->conn.trans->name, GF_LOG_CRITICAL, "cannot lookup the saved " +                gf_log (clnt->conn.trans->name, GF_LOG_CRITICAL, +                        "cannot lookup the saved "                          "frame corresponding to xid (%d)", info->xid);                  goto out;          } @@ -633,7 +635,8 @@ rpc_clnt_reply_init (rpc_clnt_connection_t *conn, rpc_transport_pollin_t *msg,                  goto out;          } -        gf_log (conn->trans->name, GF_LOG_TRACE, "received rpc message (RPC XID: 0x%ux" +        gf_log (conn->trans->name, GF_LOG_TRACE, +                "received rpc message (RPC XID: 0x%ux"                  " Program: %s, ProgVers: %d, Proc: %d) from rpc-transport (%s)",                  saved_frame->rpcreq->xid,                  saved_frame->rpcreq->prog->progname, @@ -831,8 +834,8 @@ rpc_clnt_notify (rpc_transport_t *trans, void *mydata,                  pthread_mutex_unlock (&conn->lock);                  if (clnt->notifyfn) -                        ret = clnt->notifyfn (clnt, clnt->mydata, RPC_CLNT_DISCONNECT, -                                              NULL); +                        ret = clnt->notifyfn (clnt, clnt->mydata, +                                              RPC_CLNT_DISCONNECT, NULL);                  break;          } @@ -878,7 +881,8 @@ rpc_clnt_notify (rpc_transport_t *trans, void *mydata,          case RPC_TRANSPORT_CONNECT:          {                  if (clnt->notifyfn) -                        ret = clnt->notifyfn (clnt, clnt->mydata, RPC_CLNT_CONNECT, NULL); +                        ret = clnt->notifyfn (clnt, clnt->mydata, +                                              RPC_CLNT_CONNECT, NULL);                  break;          } @@ -1051,7 +1055,8 @@ xdr_serialize_glusterfs_auth (char *dest, struct auth_glusterfs_parms *au)                         XDR_ENCODE);          if (!xdr_auth_glusterfs_parms (&xdr, au)) { -                gf_log (THIS->name, GF_LOG_WARNING, "failed to encode auth glusterfs elements"); +                gf_log (THIS->name, GF_LOG_WARNING, +                        "failed to encode auth glusterfs elements");                  ret = -1;                  goto ret;          } @@ -1145,7 +1150,8 @@ out:  struct iobuf *  rpc_clnt_record_build_record (struct rpc_clnt *clnt, int prognum, int progver,                                int procnum, size_t payload, uint64_t xid, -                              struct auth_glusterfs_parms *au, struct iovec *recbuf) +                              struct auth_glusterfs_parms *au, +                              struct iovec *recbuf)  {          struct rpc_msg           request                            = {0, };          struct iobuf            *request_iob                        = NULL; diff --git a/rpc/rpc-lib/src/rpc-common.c b/rpc/rpc-lib/src/rpc-common.c index db7b92834e7..d62ed42042a 100644 --- a/rpc/rpc-lib/src/rpc-common.c +++ b/rpc/rpc-lib/src/rpc-common.c @@ -89,7 +89,8 @@ xdr_gf_prog_detail (XDR *xdrs, gf_prog_detail *objp)  		 return FALSE;  	 if (!xdr_u_quad_t (xdrs, &objp->progver))  		 return FALSE; -	 if (!xdr_pointer (xdrs, (char **)&objp->next, sizeof (gf_prog_detail), (xdrproc_t) xdr_gf_prog_detail)) +	 if (!xdr_pointer (xdrs, (char **)&objp->next, sizeof (gf_prog_detail), +                           (xdrproc_t) xdr_gf_prog_detail))  		 return FALSE;  	return TRUE;  } @@ -103,7 +104,8 @@ xdr_gf_dump_rsp (XDR *xdrs, gf_dump_rsp *objp)  		 return FALSE;  	 if (!xdr_int (xdrs, &objp->op_errno))  		 return FALSE; -	 if (!xdr_pointer (xdrs, (char **)&objp->prog, sizeof (gf_prog_detail), (xdrproc_t) xdr_gf_prog_detail)) +	 if (!xdr_pointer (xdrs, (char **)&objp->prog, sizeof (gf_prog_detail), +                           (xdrproc_t) xdr_gf_prog_detail))  		 return FALSE;  	return TRUE;  } diff --git a/rpc/rpc-lib/src/rpc-transport.c b/rpc/rpc-lib/src/rpc-transport.c index 082ceec6e7b..b7245a8c9b8 100644 --- a/rpc/rpc-lib/src/rpc-transport.c +++ b/rpc/rpc-lib/src/rpc-transport.c @@ -525,7 +525,7 @@ rpc_transport_pollin_destroy (rpc_transport_pollin_t *pollin)          if (pollin->iobref) {                  iobref_unref (pollin->iobref);          } -  +          if (pollin->hdr_iobuf) {                  iobuf_unref (pollin->hdr_iobuf);          } @@ -909,7 +909,8 @@ rpc_transport_unref (rpc_transport_t *this)  	if (refcount == 0) {                  if (this->mydata) -                        this->notify (this, this->mydata, RPC_TRANSPORT_CLEANUP, NULL); +                        this->notify (this, this->mydata, RPC_TRANSPORT_CLEANUP, +                                      NULL);  		rpc_transport_destroy (this);  	} @@ -978,7 +979,8 @@ out:  }  int -rpc_transport_inet_options_build (dict_t **options, const char *hostname, int port) +rpc_transport_inet_options_build (dict_t **options, const char *hostname, +                                  int port)  {          dict_t          *dict = NULL;          char            *host = NULL; @@ -1000,15 +1002,15 @@ rpc_transport_inet_options_build (dict_t **options, const char *hostname, int po          ret = dict_set_dynstr (dict, "remote-host", host);          if (ret) { -                gf_log (THIS->name, GF_LOG_WARNING, "failed to set remote-host with %s", -                        host); +                gf_log (THIS->name, GF_LOG_WARNING, +                        "failed to set remote-host with %s", host);                  goto out;          }          ret = dict_set_int32 (dict, "remote-port", port);          if (ret) { -                gf_log (THIS->name, GF_LOG_WARNING, "failed to set remote-port with %d", -                        port); +                gf_log (THIS->name, GF_LOG_WARNING, +                        "failed to set remote-port with %d", port);                  goto out;          }          ret = dict_set_str (dict, "transport.address-family", "inet/inet6"); diff --git a/rpc/rpc-lib/src/rpc-transport.h b/rpc/rpc-lib/src/rpc-transport.h index f8396f572eb..5790b23f4f8 100644 --- a/rpc/rpc-lib/src/rpc-transport.h +++ b/rpc/rpc-lib/src/rpc-transport.h @@ -188,7 +188,7 @@ struct rpc_transport {                                                * transport came from. valid only                                                * on server process.                                                */ -         +  	void                      *private;          void                      *xl_private;          void                      *xl;       /* Used for THIS */ @@ -203,7 +203,7 @@ struct rpc_transport {  	data_t                    *buf;   	int32_t                  (*init)   (rpc_transport_t *this);  	void                     (*fini)   (rpc_transport_t *this); -        int32_t                  (*validate_options) (rpc_transport_t *this,  +        int32_t                  (*validate_options) (rpc_transport_t *this,                                                        char **op_errstr);          int                      (*reconfigure) (rpc_transport_t *this, dict_t *options);          rpc_transport_notify_t     notify; diff --git a/rpc/rpc-lib/src/rpcsvc-auth.c b/rpc/rpc-lib/src/rpcsvc-auth.c index fcf4617ca9b..558ada509f0 100644 --- a/rpc/rpc-lib/src/rpcsvc-auth.c +++ b/rpc/rpc-lib/src/rpcsvc-auth.c @@ -318,8 +318,8 @@ rpcsvc_authenticate (rpcsvc_request_t *req)          if (!req)                  return ret; -        //minauth = rpcsvc_request_prog_minauth (req); -        minauth = 1; +        /* FIXME use rpcsvc_request_prog_minauth() */ +        minauth = 0;          if (minauth > rpcsvc_request_cred_flavour (req)) {                  gf_log (GF_RPCSVC, GF_LOG_WARNING, "Auth too weak");                  rpcsvc_request_set_autherr (req, AUTH_TOOWEAK); @@ -339,6 +339,93 @@ err:          return ret;  } +int +rpcsvc_auth_array (rpcsvc_t *svc, char *volname, int *autharr, int arrlen) +{ +        int             count = 0; +        int             gen = RPCSVC_AUTH_REJECT; +        int             spec = RPCSVC_AUTH_REJECT; +        int             final = RPCSVC_AUTH_REJECT; +        char            *srchstr = NULL; +        char            *valstr = NULL; +        gf_boolean_t    boolval = _gf_false; +        int             ret = 0; + +        struct rpcsvc_auth_list *auth = NULL; +        struct rpcsvc_auth_list *tmp = NULL; + +        if ((!svc) || (!autharr) || (!volname)) +                return -1; + +        memset (autharr, 0, arrlen * sizeof(int)); +        if (list_empty (&svc->authschemes)) { +                gf_log (GF_RPCSVC, GF_LOG_ERROR, "No authentication!"); +                goto err; +        } + +        list_for_each_entry_safe (auth, tmp, &svc->authschemes, authlist) { +                if (count >= arrlen) +                        break; + +                gen = gf_asprintf (&srchstr, "rpc-auth.%s", auth->name); +                if (gen == -1) { +                        count = -1; +                        goto err; +                } + +                gen = RPCSVC_AUTH_REJECT; +                if (dict_get (svc->options, srchstr)) { +                        ret = dict_get_str (svc->options, srchstr, &valstr); +                        if (ret == 0) { +                                ret = gf_string2boolean (valstr, &boolval); +                                if (ret == 0) { +                                        if (boolval == _gf_true) +                                                gen = RPCSVC_AUTH_ACCEPT; +                                } else +                                        gf_log (GF_RPCSVC, GF_LOG_ERROR, "Faile" +                                                "d to read auth val"); +                        } else +                                gf_log (GF_RPCSVC, GF_LOG_ERROR, "Faile" +                                        "d to read auth val"); +                } + +                GF_FREE (srchstr); +                spec = gf_asprintf (&srchstr, "rpc-auth.%s.%s", auth->name, +                                    volname); +                if (spec == -1) { +                        count = -1; +                        goto err; +                } + +                spec = RPCSVC_AUTH_DONTCARE; +                if (dict_get (svc->options, srchstr)) { +                        ret = dict_get_str (svc->options, srchstr, &valstr); +                        if (ret == 0) { +                                ret = gf_string2boolean (valstr, &boolval); +                                if (ret == 0) { +                                        if (boolval == _gf_true) +                                                spec = RPCSVC_AUTH_ACCEPT; +                                        else +                                                spec = RPCSVC_AUTH_REJECT; +                                } else +                                        gf_log (GF_RPCSVC, GF_LOG_ERROR, "Faile" +                                                "d to read auth val"); +                        } else +                                gf_log (GF_RPCSVC, GF_LOG_ERROR, "Faile" +                                        "d to read auth val"); +                } + +                GF_FREE (srchstr); +                final = rpcsvc_combine_gen_spec_volume_checks (gen, spec); +                if (final == RPCSVC_AUTH_ACCEPT) { +                        autharr[count] = auth->auth->authnum; +                        ++count; +                } +        } + +err: +        return count; +}  gid_t *  rpcsvc_auth_unix_auxgids (rpcsvc_request_t *req, int *arrlen) diff --git a/rpc/rpc-lib/src/rpcsvc-common.h b/rpc/rpc-lib/src/rpcsvc-common.h index 442049433a7..233dac53c27 100644 --- a/rpc/rpc-lib/src/rpcsvc-common.h +++ b/rpc/rpc-lib/src/rpcsvc-common.h @@ -60,7 +60,7 @@ typedef struct rpcsvc_state {          /* Allow insecure ports. */          int                     allow_insecure; - +        gf_boolean_t            register_portmap;          glusterfs_ctx_t         *ctx;          /* list of connections which will listen for incoming connections */ diff --git a/rpc/rpc-lib/src/rpcsvc.c b/rpc/rpc-lib/src/rpcsvc.c index 519d4e3466a..10198b0f35e 100644 --- a/rpc/rpc-lib/src/rpcsvc.c +++ b/rpc/rpc-lib/src/rpcsvc.c @@ -105,8 +105,33 @@ out:          return;  } +rpcsvc_vector_sizer +rpcsvc_get_program_vector_sizer (rpcsvc_t *svc, uint32_t prognum, +                                 uint32_t progver, uint32_t procnum) +{ +        rpcsvc_program_t        *program = NULL; +        char                    found    = 0; +        if (!svc) +                return NULL; +        pthread_mutex_lock (&svc->rpclock); +        { +                list_for_each_entry (program, &svc->programs, program) { +                        if ((program->prognum == prognum) +                            && (program->progver == progver)) { +                                found = 1; +                                break; +                        } +                } +        } +        pthread_mutex_unlock (&svc->rpclock); + +        if (found) +                return program->actors[procnum].vector_sizer; +        else +                return NULL; +}  /* This needs to change to returning errors, since   * we need to return RPC specific error messages when some @@ -442,8 +467,10 @@ rpcsvc_handle_rpc_call (rpcsvc_t *svc, rpc_transport_t *trans,                  gf_log ("rpcsvc", GF_LOG_TRACE, "Client port: %d", (int)port); -                if ((port > 1024) && (0 == svc->allow_insecure)) {  //Non-privileged user, fail request -                        gf_log ("glusterd", GF_LOG_ERROR, "Request received from non-" +                if ((port > 1024) && (0 == svc->allow_insecure)) { +                        /* Non-privileged user, fail request */ +                        gf_log ("glusterd", GF_LOG_ERROR, +                                "Request received from non-"                                  "privileged port. Failing request");                          return -1;                  } @@ -505,10 +532,10 @@ rpcsvc_handle_disconnect (rpcsvc_t *svc, rpc_transport_t *trans)          rpcsvc_notify_wrapper_t *wrappers = NULL, *wrapper;          int32_t                  ret      = -1, i = 0, wrapper_count = 0;          rpcsvc_listener_t       *listener = NULL; -  +          event = (trans->listener == NULL) ? RPCSVC_EVENT_LISTENER_DEAD                  : RPCSVC_EVENT_DISCONNECT; -  +          pthread_mutex_lock (&svc->rpclock);          {                  wrappers = GF_CALLOC (svc->notify_count, sizeof (*wrapper), @@ -516,35 +543,35 @@ rpcsvc_handle_disconnect (rpcsvc_t *svc, rpc_transport_t *trans)                  if (!wrappers) {                          goto unlock;                  } -  +                  list_for_each_entry (wrapper, &svc->notify, list) {                          if (wrapper->notify) {                                  wrappers[i++] = *wrapper;                          }                  } -  +                  wrapper_count = i;          }  unlock:          pthread_mutex_unlock (&svc->rpclock); -  +          if (wrappers) {                  for (i = 0; i < wrapper_count; i++) {                          wrappers[i].notify (svc, wrappers[i].data,                                              event, trans);                  } -  +                  GF_FREE (wrappers);          } -  +          if (event == RPCSVC_EVENT_LISTENER_DEAD) {                  listener = rpcsvc_get_listener (svc, -1, trans->listener);                  rpcsvc_listener_destroy (listener);          } -  +          return ret;  } -  +  int  rpcsvc_notify (rpc_transport_t *trans, void *mydata, @@ -1114,6 +1141,11 @@ out:          return ret;  } +int +rpcsvc_register_portmap_enabled (rpcsvc_t *svc) +{ +        return svc->register_portmap; +}  int32_t  rpcsvc_get_listener_port (rpcsvc_listener_t *listener) @@ -1152,7 +1184,7 @@ rpcsvc_get_listener (rpcsvc_t *svc, uint16_t port, rpc_transport_t *trans)  {          rpcsvc_listener_t  *listener      = NULL;          char                found         = 0; -        uint32_t            listener_port = 0;  +        uint32_t            listener_port = 0;          if (!svc) {                  goto out; @@ -1343,7 +1375,7 @@ rpcsvc_create_listener (rpcsvc_t *svc, dict_t *options, char *name)  {          rpc_transport_t   *trans    = NULL;          rpcsvc_listener_t *listener = NULL; -        int32_t            ret      = -1;  +        int32_t            ret      = -1;          if (!svc || !options) {                  goto out; @@ -1577,7 +1609,6 @@ out:          return ret;  } -  static void  free_prog_details (gf_dump_rsp *rsp)  { @@ -1670,8 +1701,39 @@ fail:  int  rpcsvc_init_options (rpcsvc_t *svc, dict_t *options)  { +        char            *optstr = NULL; +        int             ret = -1; + +        if ((!svc) || (!options)) +                return -1; +          svc->memfactor = RPCSVC_DEFAULT_MEMFACTOR; -        return 0; + +        svc->register_portmap = _gf_true; +        if (dict_get (options, "rpc.register-with-portmap")) { +                ret = dict_get_str (options, "rpc.register-with-portmap", +                                    &optstr); +                if (ret < 0) { +                        gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to parse " +                                "dict"); +                        goto out; +                } + +                ret = gf_string2boolean (optstr, &svc->register_portmap); +                if (ret < 0) { +                        gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to parse bool " +                                "string"); +                        goto out; +                } +        } + +        if (!svc->register_portmap) +                gf_log (GF_RPCSVC, GF_LOG_DEBUG, "Portmap registration " +                        "disabled"); + +        ret = 0; +out: +        return ret;  }  int @@ -1789,6 +1851,531 @@ free_svc:  } +int +rpcsvc_transport_peer_check_search (dict_t *options, char *pattern, char *clstr) +{ +        int                     ret = -1; +        char                    *addrtok = NULL; +        char                    *addrstr = NULL; +        char                    *svptr = NULL; + +        if ((!options) || (!clstr)) +                return -1; + +        if (!dict_get (options, pattern)) +                return -1; + +        ret = dict_get_str (options, pattern, &addrstr); +        if (ret < 0) { +                ret = -1; +                goto err; +        } + +        if (!addrstr) { +                ret = -1; +                goto err; +        } + +        addrtok = strtok_r (addrstr, ",", &svptr); +        while (addrtok) { + +                /* CASEFOLD not present on Solaris */ +#ifdef FNM_CASEFOLD +                ret = fnmatch (addrtok, clstr, FNM_CASEFOLD); +#else +                ret = fnmatch (addrtok, clstr, 0); +#endif +                if (ret == 0) +                        goto err; + +                addrtok = strtok_r (NULL, ",", &svptr); +        } + +        ret = -1; +err: + +        return ret; +} + + +int +rpcsvc_transport_peer_check_allow (dict_t *options, char *volname, char *clstr) +{ +        int     ret = RPCSVC_AUTH_DONTCARE; +        char    *srchstr = NULL; +        char    globalrule[] = "rpc-auth.addr.allow"; + +        if ((!options) || (!clstr)) +                return ret; + +        /* If volname is NULL, then we're searching for the general rule to +         * determine the current address in clstr is allowed or not for all +         * subvolumes. +         */ +        if (volname) { +                ret = gf_asprintf (&srchstr, "rpc-auth.addr.%s.allow", volname); +                if (ret == -1) { +                        gf_log (GF_RPCSVC, GF_LOG_ERROR, "asprintf failed"); +                        ret = RPCSVC_AUTH_DONTCARE; +                        goto out; +                } +        } else +                srchstr = globalrule; + +        ret = rpcsvc_transport_peer_check_search (options, srchstr, clstr); +        if (volname) +                GF_FREE (srchstr); + +        if (ret == 0) +                ret = RPCSVC_AUTH_ACCEPT; +        else +                ret = RPCSVC_AUTH_DONTCARE; +out: +        return ret; +} + +int +rpcsvc_transport_peer_check_reject (dict_t *options, char *volname, char *clstr) +{ +        int     ret = RPCSVC_AUTH_DONTCARE; +        char    *srchstr = NULL; +        char    generalrule[] = "rpc-auth.addr.reject"; + +        if ((!options) || (!clstr)) +                return ret; + +        if (volname) { +                ret = gf_asprintf (&srchstr, "rpc-auth.addr.%s.reject", +                                   volname); +                if (ret == -1) { +                        gf_log (GF_RPCSVC, GF_LOG_ERROR, "asprintf failed"); +                        ret = RPCSVC_AUTH_REJECT; +                        goto out; +                } +        } else +                srchstr = generalrule; + +        ret = rpcsvc_transport_peer_check_search (options, srchstr, clstr); +        if (volname) +                GF_FREE (srchstr); + +        if (ret == 0) +                ret = RPCSVC_AUTH_REJECT; +        else +                ret = RPCSVC_AUTH_DONTCARE; +out: +        return ret; +} + + +/* This function tests the results of the allow rule and the reject rule to + * combine them into a single result that can be used to determine if the + * connection should be allowed to proceed. + * Heres the test matrix we need to follow in this function. + * + * A -  Allow, the result of the allow test. Never returns R. + * R - Reject, result of the reject test. Never returns A. + * Both can return D or dont care if no rule was given. + * + * | @allow | @reject | Result | + * |    A   |   R     | R      | + * |    D   |   D     | D      | + * |    A   |   D     | A      | + * |    D   |   R     | R      | + */ +int +rpcsvc_combine_allow_reject_volume_check (int allow, int reject) +{ +        int     final = RPCSVC_AUTH_REJECT; + +        /* If allowed rule allows but reject rule rejects, we stay cautious +         * and reject. */ +        if ((allow == RPCSVC_AUTH_ACCEPT) && (reject == RPCSVC_AUTH_REJECT)) +                final = RPCSVC_AUTH_REJECT; +        /* if both are dont care, that is user did not specify for either allow +         * or reject, we leave it up to the general rule to apply, in the hope +         * that there is one. +         */ +        else if ((allow == RPCSVC_AUTH_DONTCARE) && +                 (reject == RPCSVC_AUTH_DONTCARE)) +                final = RPCSVC_AUTH_DONTCARE; +        /* If one is dont care, the other one applies. */ +        else if ((allow == RPCSVC_AUTH_ACCEPT) && +                 (reject == RPCSVC_AUTH_DONTCARE)) +                final = RPCSVC_AUTH_ACCEPT; +        else if ((allow == RPCSVC_AUTH_DONTCARE) && +                 (reject == RPCSVC_AUTH_REJECT)) +                final = RPCSVC_AUTH_REJECT; + +        return final; +} + + +/* Combines the result of the general rule test against, the specific rule + * to determine final permission for the client's address. + * + * | @gen   | @spec   | Result | + * |    A   |   A     | A      | + * |    A   |   R     | R      | + * |    A   |   D     | A      | + * |    D   |   A     | A      | + * |    D   |   R     | R      | + * |    D   |   D     | D      | + * |    R   |   A     | A      | + * |    R   |   D     | R      | + * |    R   |   R     | R      | + */ +int +rpcsvc_combine_gen_spec_addr_checks (int gen, int spec) +{ +        int     final = RPCSVC_AUTH_REJECT; + +        if ((gen == RPCSVC_AUTH_ACCEPT) && (spec == RPCSVC_AUTH_ACCEPT)) +                final = RPCSVC_AUTH_ACCEPT; +        else if ((gen == RPCSVC_AUTH_ACCEPT) && (spec == RPCSVC_AUTH_REJECT)) +                final = RPCSVC_AUTH_REJECT; +        else if ((gen == RPCSVC_AUTH_ACCEPT) && (spec == RPCSVC_AUTH_DONTCARE)) +                final = RPCSVC_AUTH_ACCEPT; +        else if ((gen == RPCSVC_AUTH_DONTCARE) && (spec == RPCSVC_AUTH_ACCEPT)) +                final = RPCSVC_AUTH_ACCEPT; +        else if ((gen == RPCSVC_AUTH_DONTCARE) && (spec == RPCSVC_AUTH_REJECT)) +                final = RPCSVC_AUTH_REJECT; +        else if ((gen == RPCSVC_AUTH_DONTCARE) && (spec== RPCSVC_AUTH_DONTCARE)) +                final = RPCSVC_AUTH_DONTCARE; +        else if ((gen == RPCSVC_AUTH_REJECT) && (spec == RPCSVC_AUTH_ACCEPT)) +                final = RPCSVC_AUTH_ACCEPT; +        else if ((gen == RPCSVC_AUTH_REJECT) && (spec == RPCSVC_AUTH_DONTCARE)) +                final = RPCSVC_AUTH_REJECT; +        else if ((gen == RPCSVC_AUTH_REJECT) && (spec == RPCSVC_AUTH_REJECT)) +                final = RPCSVC_AUTH_REJECT; + +        return final; +} + + + +/* Combines the result of the general rule test against, the specific rule + * to determine final test for the connection coming in for a given volume. + * + * | @gen   | @spec   | Result | + * |    A   |   A     | A      | + * |    A   |   R     | R      | + * |    A   |   D     | A      | + * |    D   |   A     | A      | + * |    D   |   R     | R      | + * |    D   |   D     | R      |, special case, we intentionally disallow this. + * |    R   |   A     | A      | + * |    R   |   D     | R      | + * |    R   |   R     | R      | + */ +int +rpcsvc_combine_gen_spec_volume_checks (int gen, int spec) +{ +        int     final = RPCSVC_AUTH_REJECT; + +        if ((gen == RPCSVC_AUTH_ACCEPT) && (spec == RPCSVC_AUTH_ACCEPT)) +                final = RPCSVC_AUTH_ACCEPT; +        else if ((gen == RPCSVC_AUTH_ACCEPT) && (spec == RPCSVC_AUTH_REJECT)) +                final = RPCSVC_AUTH_REJECT; +        else if ((gen == RPCSVC_AUTH_ACCEPT) && (spec == RPCSVC_AUTH_DONTCARE)) +                final = RPCSVC_AUTH_ACCEPT; +        else if ((gen == RPCSVC_AUTH_DONTCARE) && (spec == RPCSVC_AUTH_ACCEPT)) +                final = RPCSVC_AUTH_ACCEPT; +        else if ((gen == RPCSVC_AUTH_DONTCARE) && (spec == RPCSVC_AUTH_REJECT)) +                final = RPCSVC_AUTH_REJECT; +        /* On no rule, we reject. */ +        else if ((gen == RPCSVC_AUTH_DONTCARE) && (spec== RPCSVC_AUTH_DONTCARE)) +                final = RPCSVC_AUTH_REJECT; +        else if ((gen == RPCSVC_AUTH_REJECT) && (spec == RPCSVC_AUTH_ACCEPT)) +                final = RPCSVC_AUTH_ACCEPT; +        else if ((gen == RPCSVC_AUTH_REJECT) && (spec == RPCSVC_AUTH_DONTCARE)) +                final = RPCSVC_AUTH_REJECT; +        else if ((gen == RPCSVC_AUTH_REJECT) && (spec == RPCSVC_AUTH_REJECT)) +                final = RPCSVC_AUTH_REJECT; + +        return final; +} + + +int +rpcsvc_transport_peer_check_name (dict_t *options, char *volname, +                                  rpc_transport_t *trans) +{ +        int     ret = RPCSVC_AUTH_REJECT; +        int     aret = RPCSVC_AUTH_REJECT; +        int     rjret = RPCSVC_AUTH_REJECT; +        char    clstr[RPCSVC_PEER_STRLEN]; + +        if (!trans) +                return ret; + +        ret = rpcsvc_transport_peername (trans, clstr, RPCSVC_PEER_STRLEN); +        if (ret != 0) { +                gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to get remote addr: " +                        "%s", gai_strerror (ret)); +                ret = RPCSVC_AUTH_REJECT; +                goto err; +        } + +        aret = rpcsvc_transport_peer_check_allow (options, volname, clstr); +        rjret = rpcsvc_transport_peer_check_reject (options, volname, clstr); + +        ret = rpcsvc_combine_allow_reject_volume_check (aret, rjret); + +err: +        return ret; +} + + +int +rpcsvc_transport_peer_check_addr (dict_t *options, char *volname, +                                  rpc_transport_t *trans) +{ +        int     ret = RPCSVC_AUTH_REJECT; +        int     aret = RPCSVC_AUTH_DONTCARE; +        int     rjret = RPCSVC_AUTH_REJECT; +        char    clstr[RPCSVC_PEER_STRLEN]; +        struct sockaddr_storage sastorage = {0,}; + +        if (!trans) +                return ret; + +        ret = rpcsvc_transport_peeraddr (trans, clstr, RPCSVC_PEER_STRLEN, +                                         &sastorage, sizeof (sastorage)); +        if (ret != 0) { +                gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to get remote addr: " +                        "%s", gai_strerror (ret)); +                ret = RPCSVC_AUTH_REJECT; +                goto err; +        } + +        aret = rpcsvc_transport_peer_check_allow (options, volname, clstr); +        rjret = rpcsvc_transport_peer_check_reject (options, volname, clstr); + +        ret = rpcsvc_combine_allow_reject_volume_check (aret, rjret); +err: +        return ret; +} + + +int +rpcsvc_transport_check_volume_specific (dict_t *options, char *volname, +                                        rpc_transport_t *trans) +{ +        int             namechk = RPCSVC_AUTH_REJECT; +        int             addrchk = RPCSVC_AUTH_REJECT; +        gf_boolean_t    namelookup = _gf_true; +        char            *namestr = NULL; +        int             ret = 0; + +        if ((!options) || (!volname) || (!trans)) +                return RPCSVC_AUTH_REJECT; + +        /* Enabled by default */ +        if ((dict_get (options, "rpc-auth.addr.namelookup"))) { +                ret = dict_get_str (options, "rpc-auth.addr.namelookup" +                                    , &namestr); +                if (ret == 0) +                        ret = gf_string2boolean (namestr, &namelookup); +        } + +        /* We need two separate checks because the rules with addresses in them +         * can be network addresses which can be general and names can be +         * specific which will over-ride the network address rules. +         */ +        if (namelookup) +                namechk = rpcsvc_transport_peer_check_name (options, volname, +                                                            trans); +        addrchk = rpcsvc_transport_peer_check_addr (options, volname, trans); + +        if (namelookup) +                ret = rpcsvc_combine_gen_spec_addr_checks (addrchk, +                                                               namechk); +        else +                ret = addrchk; + +        return ret; +} + + +int +rpcsvc_transport_check_volume_general (dict_t *options, rpc_transport_t *trans) +{ +        int             addrchk = RPCSVC_AUTH_REJECT; +        int             namechk = RPCSVC_AUTH_REJECT; +        gf_boolean_t    namelookup = _gf_true; +        char            *namestr = NULL; +        int             ret = 0; + +        if ((!options) || (!trans)) +                return RPCSVC_AUTH_REJECT; + +        /* Enabled by default */ +        if ((dict_get (options, "rpc-auth.addr.namelookup"))) { +                ret = dict_get_str (options, "rpc-auth.addr.namelookup" +                                    , &namestr); +                if (ret == 0) +                        ret = gf_string2boolean (namestr, &namelookup); +        } + +        /* We need two separate checks because the rules with addresses in them +         * can be network addresses which can be general and names can be +         * specific which will over-ride the network address rules. +         */ +        if (namelookup) +                namechk = rpcsvc_transport_peer_check_name (options, NULL, trans); +        addrchk = rpcsvc_transport_peer_check_addr (options, NULL, trans); + +        if (namelookup) +                ret = rpcsvc_combine_gen_spec_addr_checks (addrchk, +                                                               namechk); +        else +                ret = addrchk; + +        return ret; +} + +int +rpcsvc_transport_peer_check (dict_t *options, char *volname, +                             rpc_transport_t *trans) +{ +        int     general_chk = RPCSVC_AUTH_REJECT; +        int     specific_chk = RPCSVC_AUTH_REJECT; + +        if ((!options) || (!volname) || (!trans)) +                return RPCSVC_AUTH_REJECT; + +        general_chk = rpcsvc_transport_check_volume_general (options, trans); +        specific_chk = rpcsvc_transport_check_volume_specific (options, volname, +                                                               trans); + +        return rpcsvc_combine_gen_spec_volume_checks (general_chk, +                                                      specific_chk); +} + + +int +rpcsvc_transport_privport_check (rpcsvc_t *svc, char *volname, +                                 rpc_transport_t *trans) +{ +        struct sockaddr_storage sastorage = {0,}; +        struct sockaddr_in     *sa = NULL; +        int                     ret = RPCSVC_AUTH_REJECT; +        socklen_t               sasize = sizeof (sa); +        char                    *srchstr = NULL; +        char                    *valstr = NULL; +        int                     globalinsecure = RPCSVC_AUTH_REJECT; +        int                     exportinsecure = RPCSVC_AUTH_DONTCARE; +        uint16_t                port = 0; +        gf_boolean_t            insecure = _gf_false; + +        if ((!svc) || (!volname) || (!trans)) +                return ret; + +        sa = (struct sockaddr_in*) &sastorage; +        ret = rpcsvc_transport_peeraddr (trans, NULL, 0, &sastorage, +                                         sasize); +        if (ret != 0) { +                gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to get peer addr: %s", +                        gai_strerror (ret)); +                ret = RPCSVC_AUTH_REJECT; +                goto err; +        } + +        port = ntohs (sa->sin_port); +        gf_log (GF_RPCSVC, GF_LOG_TRACE, "Client port: %d", (int)port); +        /* If the port is already a privileged one, dont bother with checking +         * options. +         */ +        if (port <= 1024) { +                ret = RPCSVC_AUTH_ACCEPT; +                goto err; +        } + +        /* Disabled by default */ +        if ((dict_get (svc->options, "rpc-auth.ports.insecure"))) { +                ret = dict_get_str (svc->options, "rpc-auth.ports.insecure" +                                    , &srchstr); +                if (ret == 0) { +                        ret = gf_string2boolean (srchstr, &insecure); +                        if (ret == 0) { +                                if (insecure == _gf_true) +                                        globalinsecure = RPCSVC_AUTH_ACCEPT; +                        } else +                                gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to" +                                        " read rpc-auth.ports.insecure value"); +                } else +                        gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to" +                                " read rpc-auth.ports.insecure value"); +        } + +        /* Disabled by default */ +        ret = gf_asprintf (&srchstr, "rpc-auth.ports.%s.insecure", volname); +        if (ret == -1) { +                gf_log (GF_RPCSVC, GF_LOG_ERROR, "asprintf failed"); +                ret = RPCSVC_AUTH_REJECT; +                goto err; +        } + +        if (dict_get (svc->options, srchstr)) { +                ret = dict_get_str (svc->options, srchstr, &valstr); +                if (ret == 0) { +                        ret = gf_string2boolean (srchstr, &insecure); +                        if (ret == 0) { +                                if (insecure == _gf_true) +                                       exportinsecure = RPCSVC_AUTH_ACCEPT; +                                else +                                        exportinsecure = RPCSVC_AUTH_REJECT; +                        } else +                                gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to" +                                        " read rpc-auth.ports.insecure value"); +                } else +                        gf_log (GF_RPCSVC, GF_LOG_ERROR, "Failed to" +                                " read rpc-auth.ports.insecure value"); +        } + +        ret = rpcsvc_combine_gen_spec_volume_checks (globalinsecure, +                                                         exportinsecure); +        if (ret == RPCSVC_AUTH_ACCEPT) +                gf_log (GF_RPCSVC, GF_LOG_DEBUG, "Unprivileged port allowed"); +        else +                gf_log (GF_RPCSVC, GF_LOG_DEBUG, "Unprivileged port not" +                        " allowed"); + +err: +        return ret; +} + + +char * +rpcsvc_volume_allowed (dict_t *options, char *volname) +{ +        char    globalrule[] = "rpc-auth.addr.allow"; +        char    *srchstr = NULL; +        char    *addrstr = NULL; +        int     ret = -1; + +        if ((!options) || (!volname)) +                return NULL; + +        ret = gf_asprintf (&srchstr, "rpc-auth.addr.%s.allow", volname); +        if (ret == -1) { +                gf_log (GF_RPCSVC, GF_LOG_ERROR, "asprintf failed"); +                goto out; +        } + +        if (!dict_get (options, srchstr)) { +                GF_FREE (srchstr); +                srchstr = globalrule; +                ret = dict_get_str (options, srchstr, &addrstr); +        } else +                ret = dict_get_str (options, srchstr, &addrstr); + +out: +        return addrstr; +} + +  rpcsvc_actor_t gluster_dump_actors[] = {          [GF_DUMP_NULL] = {"NULL", GF_DUMP_NULL, NULL, NULL, NULL },          [GF_DUMP_DUMP] = {"DUMP", GF_DUMP_DUMP, rpcsvc_dump, NULL, NULL }, diff --git a/rpc/rpc-lib/src/rpcsvc.h b/rpc/rpc-lib/src/rpcsvc.h index 17da800fa9c..7ef6e580c22 100644 --- a/rpc/rpc-lib/src/rpcsvc.h +++ b/rpc/rpc-lib/src/rpcsvc.h @@ -249,7 +249,8 @@ struct rpcsvc_request {  };  #define rpcsvc_request_program(req) ((rpcsvc_program_t *)((req)->prog)) -#define rpcsvc_request_program_private(req) (((rpcsvc_program_t *)((req)->program))->private) +#define rpcsvc_request_procnum(req) (((req)->procnum)) +#define rpcsvc_request_program_private(req) (((rpcsvc_program_t *)((req)->prog))->private)  #define rpcsvc_request_accepted(req)    ((req)->rpc_status == MSG_ACCEPTED)  #define rpcsvc_request_accepted_success(req) ((req)->rpc_err == SUCCESS)  #define rpcsvc_request_uid(req)         ((req)->uid) @@ -257,18 +258,24 @@ struct rpcsvc_request {  #define rpcsvc_request_prog_minauth(req) (rpcsvc_request_program(req)->min_auth)  #define rpcsvc_request_cred_flavour(req) (rpcsvc_auth_flavour(req->cred))  #define rpcsvc_request_verf_flavour(req) (rpcsvc_auth_flavour(req->verf)) - +#define rpcsvc_request_service(req)      ((req)->svc)  #define rpcsvc_request_uid(req)         ((req)->uid)  #define rpcsvc_request_gid(req)         ((req)->gid)  #define rpcsvc_request_private(req)     ((req)->private)  #define rpcsvc_request_xid(req)         ((req)->xid)  #define rpcsvc_request_set_private(req,prv)  (req)->private = (void *)(prv) +#define rpcsvc_request_iobref_ref(req)  (iobref_ref ((req)->iobref))  #define rpcsvc_request_record_ref(req)  (iobuf_ref ((req)->recordiob))  #define rpcsvc_request_record_unref(req) (iobuf_unref ((req)->recordiob)) +#define rpcsvc_request_record_iob(req)   ((req)->recordiob) +#define rpcsvc_request_set_vecstate(req, state)  ((req)->vecstate = state) +#define rpcsvc_request_vecstate(req) ((req)->vecstate) +#define rpcsvc_request_transport(req) ((req)->trans)  #define RPCSVC_ACTOR_SUCCESS    0  #define RPCSVC_ACTOR_ERROR      (-1) +#define RPCSVC_ACTOR_IGNORE     (-2)  /* Functor for every type of protocol actor   * must be defined like this. @@ -285,8 +292,7 @@ struct rpcsvc_request {  typedef int (*rpcsvc_actor) (rpcsvc_request_t *req);  typedef int (*rpcsvc_vector_actor) (rpcsvc_request_t *req, struct iovec *vec,                                      int count, struct iobref *iobref); -typedef int (*rpcsvc_vector_sizer) (rpcsvc_request_t *req, ssize_t *readsize, -                                    int *newiob); +typedef int (*rpcsvc_vector_sizer) (int state, ssize_t *readsize, char *addr);  /* Every protocol actor will also need to specify the function the RPC layer   * will use to serialize or encode the message into XDR format just before @@ -410,6 +416,9 @@ rpcsvc_listener_destroy (rpcsvc_listener_t *listener);  extern int  rpcsvc_program_register_portmap (rpcsvc_program_t *newprog, uint32_t port); +extern int +rpcsvc_register_portmap_enabled (rpcsvc_t *svc); +  /* Inits the global RPC service data structures.   * Called in main.   */ @@ -542,4 +551,12 @@ int  rpcsvc_transport_unix_options_build (dict_t **options, char *filepath);  int  rpcsvc_set_allow_insecure (rpcsvc_t *svc, dict_t *options); +int +rpcsvc_auth_array (rpcsvc_t *svc, char *volname, int *autharr, int arrlen); +char * +rpcsvc_volume_allowed (dict_t *options, char *volname); +rpcsvc_vector_sizer +rpcsvc_get_program_vector_sizer (rpcsvc_t *svc, uint32_t prognum, +                                 uint32_t progver, uint32_t procnum); +  #endif diff --git a/rpc/rpc-lib/src/xdr-common.h b/rpc/rpc-lib/src/xdr-common.h index c69bfa834fb..0014e46ac1a 100644 --- a/rpc/rpc-lib/src/xdr-common.h +++ b/rpc/rpc-lib/src/xdr-common.h @@ -113,8 +113,6 @@ xdr_from_dump_req (struct iovec outmsg, void *rsp);  ssize_t  xdr_to_dump_rsp (struct iovec inmsg, void *args); -#define XDR_BYTES_PER_UNIT      4 -  /* Returns the address of the byte that follows the   * last byte used for decoding the previous xdr component.   * For eg, once the RPC call for NFS has been decoded, thie macro will return diff --git a/rpc/rpc-transport/socket/src/socket.c b/rpc/rpc-transport/socket/src/socket.c index 23889b52077..51d51bc9e85 100644 --- a/rpc/rpc-transport/socket/src/socket.c +++ b/rpc/rpc-transport/socket/src/socket.c @@ -38,6 +38,8 @@  #include "protocol-common.h"  #include "glusterfs3-xdr.h"  #include "glusterfs3.h" +#include "xdr-nfs3.h" +#include "rpcsvc.h"  #include <fcntl.h>  #include <errno.h> @@ -806,9 +808,14 @@ __socket_read_simple_request (rpc_transport_t *this)  #define rpc_verf_addr(fragcurrent) (fragcurrent - 4) +#define rpc_msgtype_addr(buf) (buf + 4) + +#define rpc_prognum_addr(buf) (buf + RPC_MSGTYPE_SIZE + 4) +#define rpc_progver_addr(buf) (buf + RPC_MSGTYPE_SIZE + 8) +#define rpc_procnum_addr(buf) (buf + RPC_MSGTYPE_SIZE + 12)  inline int -__socket_read_vectored_request (rpc_transport_t *this) +__socket_read_vectored_request (rpc_transport_t *this, rpcsvc_vector_sizer vector_sizer)  {          socket_private_t *priv                   = NULL;          int               ret                    = 0; @@ -816,8 +823,7 @@ __socket_read_vectored_request (rpc_transport_t *this)          char             *addr                   = NULL;          struct iobuf     *iobuf                  = NULL;          uint32_t          remaining_size         = 0; -        uint32_t          gluster_write_proc_len = 0; -        gfs3_write_req    write_req              = {{0,},}; +        ssize_t           readsize               = 0;          GF_VALIDATE_OR_GOTO ("socket", this, out);          GF_VALIDATE_OR_GOTO ("socket", this->private, out); @@ -826,6 +832,7 @@ __socket_read_vectored_request (rpc_transport_t *this)          switch (priv->incoming.frag.call_body.request.vector_state) {          case SP_STATE_VECTORED_REQUEST_INIT: +                priv->incoming.frag.call_body.request.vector_sizer_state = 0;                  addr = rpc_cred_addr (iobuf_ptr (priv->incoming.iobuf));                  /* also read verf flavour and verflen */ @@ -849,24 +856,13 @@ __socket_read_vectored_request (rpc_transport_t *this)          case SP_STATE_READ_CREDBYTES:                  addr = rpc_verf_addr (priv->incoming.frag.fragcurrent); +                verflen = ntoh32 (*((uint32_t *)addr)); -                /* FIXME: Also handle procedures other than glusterfs-write -                 * here -                 */ -                /* also read proc-header */ -                gluster_write_proc_len = xdr_sizeof ((xdrproc_t) xdr_gfs3_write_req, -                                                     &write_req); - -                if (gluster_write_proc_len == 0) { -                        gf_log (this->name, GF_LOG_ERROR, -                                "xdr_sizeof on gfs3_write_req failed"); -                        ret = -1; -                        goto out; +                if (verflen == 0) { +                        priv->incoming.frag.call_body.request.vector_state +                                = SP_STATE_READ_VERFBYTES; +                        goto sp_state_read_verfbytes;                  } - -                verflen = ntoh32 (*((uint32_t *)addr)) -                        + gluster_write_proc_len; -                  __socket_proto_init_pending (priv, verflen);                  priv->incoming.frag.call_body.request.vector_state @@ -883,6 +879,34 @@ __socket_read_vectored_request (rpc_transport_t *this)                  /* fall through */          case SP_STATE_READ_VERFBYTES: +sp_state_read_verfbytes: +                priv->incoming.frag.call_body.request.vector_sizer_state = +                        vector_sizer (priv->incoming.frag.call_body.request.vector_sizer_state, +                                      &readsize, +                                      priv->incoming.frag.fragcurrent); +                __socket_proto_init_pending (priv, readsize); +                priv->incoming.frag.call_body.request.vector_state +                        = SP_STATE_READING_PROGHDR; + +                /* fall through */ + +        case SP_STATE_READING_PROGHDR: +                __socket_proto_read (priv, ret); +sp_state_reading_proghdr: +                priv->incoming.frag.call_body.request.vector_sizer_state = +                        vector_sizer (priv->incoming.frag.call_body.request.vector_sizer_state, +                                      &readsize, +                                      priv->incoming.frag.fragcurrent); +                if (readsize == 0) { +                        priv->incoming.frag.call_body.request.vector_state = +                                SP_STATE_READ_PROGHDR; +                } else { +                        __socket_proto_init_pending (priv, readsize); +                        __socket_proto_read (priv, ret); +                        goto sp_state_reading_proghdr; +                } + +        case SP_STATE_READ_PROGHDR:                  if (priv->incoming.payload_vector.iov_base == NULL) {                          iobuf = iobuf_get (this->ctx->iobuf_pool);                          if (!iobuf) { @@ -941,22 +965,15 @@ out:          return ret;  } - -#define rpc_msgtype_addr(buf) (buf + 4) - -#define rpc_prognum_addr(buf) (buf + RPC_MSGTYPE_SIZE + 4) - -#define rpc_procnum_addr(buf) (buf + RPC_MSGTYPE_SIZE + 12) - -  inline int  __socket_read_request (rpc_transport_t *this)  {          socket_private_t *priv               = NULL; -        uint32_t          prognum            = 0, procnum = 0; +        uint32_t          prognum            = 0, procnum = 0, progver = 0;          uint32_t          remaining_size     = 0;          int               ret                = -1;          char             *buf                = NULL; +        rpcsvc_vector_sizer     vector_sizer = NULL;          GF_VALIDATE_OR_GOTO ("socket", this, out);          GF_VALIDATE_OR_GOTO ("socket", this->private, out); @@ -986,12 +1003,21 @@ __socket_read_request (rpc_transport_t *this)                  buf = rpc_prognum_addr (iobuf_ptr (priv->incoming.iobuf));                  prognum = ntoh32 (*((uint32_t *)buf)); +                buf = rpc_progver_addr (iobuf_ptr (priv->incoming.iobuf)); +                progver = ntoh32 (*((uint32_t *)buf)); +                  buf = rpc_procnum_addr (iobuf_ptr (priv->incoming.iobuf));                  procnum = ntoh32 (*((uint32_t *)buf)); -                if ((prognum == GLUSTER3_1_FOP_PROGRAM) -                    && (procnum == GF_FOP_WRITE)) { -                        ret = __socket_read_vectored_request (this); +                if (this->listener) { +                        /* this check is needed as rpcsvc and rpc-clnt actor structures are +                         * not same */ +                        vector_sizer = rpcsvc_get_program_vector_sizer ((rpcsvc_t *)this->mydata, +                                                                        prognum, progver, procnum); +                } + +                if (vector_sizer) { +                        ret = __socket_read_vectored_request (this, vector_sizer);                  } else {                          ret = __socket_read_simple_request (this);                  } @@ -2411,6 +2437,7 @@ socket_getpeeraddr (rpc_transport_t *this, char *peeraddr, int addrlen,          if (peeraddr != NULL) {                  ret = socket_getpeername (this, peeraddr, addrlen);          } +        ret = 0;  out:          return ret; diff --git a/rpc/rpc-transport/socket/src/socket.h b/rpc/rpc-transport/socket/src/socket.h index c52026cc829..4cc84a6d187 100644 --- a/rpc/rpc-transport/socket/src/socket.h +++ b/rpc/rpc-transport/socket/src/socket.h @@ -81,6 +81,8 @@ typedef enum {          SP_STATE_READ_CREDBYTES,        /* read credential data. */          SP_STATE_READING_VERFBYTES,          SP_STATE_READ_VERFBYTES,        /* read verifier data */ +        SP_STATE_READING_PROGHDR, +        SP_STATE_READ_PROGHDR,          SP_STATE_READING_PROG,  } sp_rpcfrag_vectored_request_state_t; @@ -112,6 +114,7 @@ struct ioq {  typedef struct {          sp_rpcfrag_request_header_state_t header_state;          sp_rpcfrag_vectored_request_state_t vector_state; +        int vector_sizer_state;  } sp_rpcfrag_request_state_t;  typedef enum { diff --git a/rpc/xdr/src/Makefile.am b/rpc/xdr/src/Makefile.am index 981f319b3a7..d239700903c 100644 --- a/rpc/xdr/src/Makefile.am +++ b/rpc/xdr/src/Makefile.am @@ -13,10 +13,12 @@ libgfxdr_la_SOURCES =  xdr-generic.c \  			glusterfs3-xdr.c glusterfs3.c \  			cli1-xdr.c cli1.c \  			glusterd1-xdr.c glusterd1.c \ -			portmap-xdr.c portmap.c +			portmap-xdr.c portmap.c \ +			xdr-nfs3.c msg-nfs3.c  noinst_HEADERS = xdr-generic.h \  		glusterfs3-xdr.h glusterfs3.h \  		cli1-xdr.h cli1.h \  		glusterd1-xdr.h glusterd1.h \ -		portmap-xdr.h portmap.h +		portmap-xdr.h portmap.h \ +		xdr-nfs3.h msg-nfs3.h diff --git a/rpc/xdr/src/msg-nfs3.c b/rpc/xdr/src/msg-nfs3.c new file mode 100644 index 00000000000..78051494b9c --- /dev/null +++ b/rpc/xdr/src/msg-nfs3.c @@ -0,0 +1,555 @@ +/* +  Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com> +  This file is part of GlusterFS. + +  GlusterFS is free software; you can redistribute it and/or modify +  it under the terms of the GNU Affero General Public License as published +  by the Free Software Foundation; either version 3 of the License, +  or (at your option) any later version. + +  GlusterFS is distributed in the hope that it will be useful, but +  WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +  Affero General Public License for more details. + +  You should have received a copy of the GNU Affero General Public License +  along with this program.  If not, see +  <http://www.gnu.org/licenses/>. +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include <sys/uio.h> +#include <rpc/rpc.h> +#include <rpc/xdr.h> +#include <sys/types.h> + +#include "xdr-nfs3.h" +#include "msg-nfs3.h" +#include "xdr-generic.h" +#include "xdr-common.h" + + +/* Decode the mount path from the network message in inmsg + * into the memory referenced by outpath.iov_base. + * The size allocated for outpath.iov_base is outpath.iov_len. + * The size of the path extracted from the message is returned. + */ +ssize_t +xdr_to_mountpath (struct iovec outpath, struct iovec inmsg) +{ +        XDR     xdr; +        ssize_t ret = -1; +        char    *mntpath = NULL; + +        if ((!outpath.iov_base) || (!inmsg.iov_base)) +                return -1; + +        xdrmem_create (&xdr, inmsg.iov_base, (unsigned int)inmsg.iov_len, +                       XDR_DECODE); + +        mntpath = outpath.iov_base; +        if (!xdr_dirpath (&xdr, (dirpath *)&mntpath)) { +                ret = -1; +                goto ret; +        } + +        ret = xdr_decoded_length (xdr); + +ret: +        return ret; +} + +/* +ssize_t +xdr_serialize_generic (struct iovec outmsg, void *res, xdrproc_t proc) +{ +        ssize_t ret = -1; +        XDR     xdr; + +        if ((!outmsg.iov_base) || (!res) || (!proc)) +                return -1; + +        xdrmem_create (&xdr, outmsg.iov_base, (unsigned int)outmsg.iov_len, +                       XDR_ENCODE); + +        if (!proc (&xdr, res)) { +                ret = -1; +                goto ret; +        } + +        ret = xdr_encoded_length (xdr); + +ret: +        return ret; +} + + +ssize_t +xdr_to_generic (struct iovec inmsg, void *args, xdrproc_t proc) +{ +        XDR     xdr; +        ssize_t ret = -1; + +        if ((!inmsg.iov_base) || (!args) || (!proc)) +                return -1; + +        xdrmem_create (&xdr, inmsg.iov_base, (unsigned int)inmsg.iov_len, +                       XDR_DECODE); + +        if (!proc (&xdr, args)) { +                ret  = -1; +                goto ret; +        } + +        ret = xdr_decoded_length (xdr); +ret: +        return ret; +} + + +ssize_t +xdr_to_generic_payload (struct iovec inmsg, void *args, xdrproc_t proc, +                            struct iovec *pendingpayload) +{ +        XDR     xdr; +        ssize_t ret = -1; + +        if ((!inmsg.iov_base) || (!args) || (!proc)) +                return -1; + +        xdrmem_create (&xdr, inmsg.iov_base, (unsigned int)inmsg.iov_len, +                       XDR_DECODE); + +        if (!proc (&xdr, args)) { +                ret  = -1; +                goto ret; +        } + +        ret = xdr_decoded_length (xdr); + +        if (pendingpayload) { +                pendingpayload->iov_base = xdr_decoded_remaining_addr (xdr); +                pendingpayload->iov_len = xdr_decoded_remaining_len (xdr); +        } + +ret: +        return ret; +} +*/ + +/* Translate the mountres3 structure in res into XDR format into memory + * referenced by outmsg.iov_base. + * Returns the number of bytes used in encoding into XDR format. + */ +ssize_t +xdr_serialize_mountres3 (struct iovec outmsg, mountres3 *res) +{ +        return xdr_serialize_generic (outmsg, (void *)res, +                                          (xdrproc_t)xdr_mountres3); +} + + +ssize_t +xdr_serialize_mountbody (struct iovec outmsg, mountbody *mb) +{ +        return xdr_serialize_generic (outmsg, (void *)mb, +                                          (xdrproc_t)xdr_mountbody); +} + +ssize_t +xdr_serialize_mountlist (struct iovec outmsg, mountlist *ml) +{ +        return xdr_serialize_generic (outmsg, (void *)ml, +                                          (xdrproc_t)xdr_mountlist); +} + + +ssize_t +xdr_serialize_mountstat3 (struct iovec outmsg, mountstat3 *m) +{ +        return xdr_serialize_generic (outmsg, (void *)m, +                                          (xdrproc_t)xdr_mountstat3); +} + + +ssize_t +xdr_to_getattr3args (struct iovec inmsg, getattr3args *ga) +{ +        return xdr_to_generic (inmsg, (void *)ga, +                                   (xdrproc_t)xdr_getattr3args); +} + + +ssize_t +xdr_serialize_getattr3res (struct iovec outmsg, getattr3res *res) +{ +        return xdr_serialize_generic (outmsg, (void *)res, +                                          (xdrproc_t)xdr_getattr3res); +} + + +ssize_t +xdr_serialize_setattr3res (struct iovec outmsg, setattr3res *res) +{ +        return xdr_serialize_generic (outmsg, (void *)res, +                                          (xdrproc_t)xdr_setattr3res); +} + + +ssize_t +xdr_to_setattr3args (struct iovec inmsg, setattr3args *sa) +{ +        return xdr_to_generic (inmsg, (void *)sa, +                                   (xdrproc_t)xdr_setattr3args); +} + + +ssize_t +xdr_serialize_lookup3res (struct iovec outmsg, lookup3res *res) +{ +        return xdr_serialize_generic (outmsg, (void *)res, +                                          (xdrproc_t)xdr_lookup3res); +} + + +ssize_t +xdr_to_lookup3args (struct iovec inmsg, lookup3args *la) +{ +        return xdr_to_generic (inmsg, (void *)la, +                                   (xdrproc_t)xdr_lookup3args); +} + + +ssize_t +xdr_to_access3args (struct iovec inmsg, access3args *ac) +{ +        return xdr_to_generic (inmsg,(void *)ac, +                                   (xdrproc_t)xdr_access3args); +} + + +ssize_t +xdr_serialize_access3res (struct iovec outmsg, access3res *res) +{ +        return xdr_serialize_generic (outmsg, (void *)res, +                                          (xdrproc_t)xdr_access3res); +} + + +ssize_t +xdr_to_readlink3args (struct iovec inmsg, readlink3args *ra) +{ +        return xdr_to_generic (inmsg, (void *)ra, +                                   (xdrproc_t)xdr_readlink3args); +} + + +ssize_t +xdr_serialize_readlink3res (struct iovec outmsg, readlink3res *res) +{ +        return xdr_serialize_generic (outmsg, (void *)res, +                                          (xdrproc_t)xdr_readlink3res); +} + + +ssize_t +xdr_to_read3args (struct iovec inmsg, read3args *ra) +{ +        return xdr_to_generic (inmsg, (void *)ra, (xdrproc_t)xdr_read3args); +} + + +ssize_t +xdr_serialize_read3res (struct iovec outmsg, read3res *res) +{ +        return xdr_serialize_generic (outmsg, (void *)res, +                                          (xdrproc_t)xdr_read3res); +} + +ssize_t +xdr_serialize_read3res_nocopy (struct iovec outmsg, read3res *res) +{ +        return xdr_serialize_generic (outmsg, (void *)res, +                                          (xdrproc_t)xdr_read3res_nocopy); +} + + +ssize_t +xdr_to_write3args (struct iovec inmsg, write3args *wa) +{ +        return xdr_to_generic (inmsg, (void *)wa,(xdrproc_t)xdr_write3args); +} + + +ssize_t +xdr_to_write3args_nocopy (struct iovec inmsg, write3args *wa, +                          struct iovec *payload) +{ +        return xdr_to_generic_payload (inmsg, (void *)wa, +                                           (xdrproc_t)xdr_write3args, payload); +} + + +ssize_t +xdr_serialize_write3res (struct iovec outmsg, write3res *res) +{ +        return xdr_serialize_generic (outmsg, (void *)res, +                                          (xdrproc_t)xdr_write3res); +} + + +ssize_t +xdr_to_create3args (struct iovec inmsg, create3args *ca) +{ +        return xdr_to_generic (inmsg, (void *)ca, +                                   (xdrproc_t)xdr_create3args); +} + + +ssize_t +xdr_serialize_create3res (struct iovec outmsg, create3res *res) +{ +        return xdr_serialize_generic (outmsg, (void *)res, +                                          (xdrproc_t)xdr_create3res); +} + + +ssize_t +xdr_serialize_mkdir3res (struct iovec outmsg, mkdir3res *res) +{ +        return xdr_serialize_generic (outmsg, (void *)res, +                                          (xdrproc_t)xdr_mkdir3res); +} + + +ssize_t +xdr_to_mkdir3args (struct iovec inmsg, mkdir3args *ma) +{ +        return xdr_to_generic (inmsg, (void *)ma, +                                   (xdrproc_t)xdr_mkdir3args); +} + + +ssize_t +xdr_to_symlink3args (struct iovec inmsg, symlink3args *sa) +{ +        return xdr_to_generic (inmsg, (void *)sa, +                                   (xdrproc_t)xdr_symlink3args); +} + + +ssize_t +xdr_serialize_symlink3res (struct iovec outmsg, symlink3res *res) +{ +        return xdr_serialize_generic (outmsg, (void *)res, +                                          (xdrproc_t)xdr_symlink3res); +} + + +ssize_t +xdr_to_mknod3args (struct iovec inmsg, mknod3args *ma) +{ +        return xdr_to_generic (inmsg, (void *)ma, +                                   (xdrproc_t)xdr_mknod3args); +} + + +ssize_t +xdr_serialize_mknod3res (struct iovec outmsg, mknod3res *res) +{ +        return xdr_serialize_generic (outmsg, (void *)res, +                                          (xdrproc_t)xdr_mknod3res); +} + + +ssize_t +xdr_to_remove3args (struct iovec inmsg, remove3args *ra) +{ +        return xdr_to_generic (inmsg, (void *)ra, +                                   (xdrproc_t)xdr_remove3args); +} + + +ssize_t +xdr_serialize_remove3res (struct iovec outmsg, remove3res *res) +{ +        return xdr_serialize_generic (outmsg, (void *)res, +                                          (xdrproc_t)xdr_remove3res); +} + + +ssize_t +xdr_to_rmdir3args (struct iovec inmsg, rmdir3args *ra) +{ +        return xdr_to_generic (inmsg, (void *)ra, +                                   (xdrproc_t)xdr_rmdir3args); +} + + +ssize_t +xdr_serialize_rmdir3res (struct iovec outmsg, rmdir3res *res) +{ +        return xdr_serialize_generic (outmsg, (void *)res, +                                          (xdrproc_t)xdr_rmdir3res); +} + + +ssize_t +xdr_serialize_rename3res (struct iovec outmsg, rename3res *res) +{ +        return xdr_serialize_generic (outmsg, (void *)res, +                                          (xdrproc_t)xdr_rename3res); +} + + +ssize_t +xdr_to_rename3args (struct iovec inmsg, rename3args *ra) +{ +        return xdr_to_generic (inmsg, (void *)ra, +                                   (xdrproc_t)xdr_rename3args); +} + + +ssize_t +xdr_serialize_link3res (struct iovec outmsg, link3res *li) +{ +        return xdr_serialize_generic (outmsg, (void *)li, +                                          (xdrproc_t)xdr_link3res); +} + + +ssize_t +xdr_to_link3args (struct iovec inmsg, link3args *la) +{ +        return xdr_to_generic (inmsg, (void *)la, (xdrproc_t)xdr_link3args); +} + + +ssize_t +xdr_to_readdir3args (struct iovec inmsg, readdir3args *rd) +{ +        return xdr_to_generic (inmsg, (void *)rd, +                                   (xdrproc_t)xdr_readdir3args); +} + + +ssize_t +xdr_serialize_readdir3res (struct iovec outmsg, readdir3res *res) +{ +        return xdr_serialize_generic (outmsg, (void *)res, +                                          (xdrproc_t)xdr_readdir3res); +} + + +ssize_t +xdr_to_readdirp3args (struct iovec inmsg, readdirp3args *rp) +{ +        return xdr_to_generic (inmsg, (void *)rp, +                                   (xdrproc_t)xdr_readdirp3args); +} + + +ssize_t +xdr_serialize_readdirp3res (struct iovec outmsg, readdirp3res *res) +{ +        return xdr_serialize_generic (outmsg, (void *)res, +                                          (xdrproc_t)xdr_readdirp3res); +} + + +ssize_t +xdr_to_fsstat3args (struct iovec inmsg, fsstat3args *fa) +{ +        return xdr_to_generic (inmsg, (void *)fa, +                                   (xdrproc_t)xdr_fsstat3args); +} + + +ssize_t +xdr_serialize_fsstat3res (struct iovec outmsg, fsstat3res *res) +{ +        return xdr_serialize_generic (outmsg, (void *)res, +                                          (xdrproc_t)xdr_fsstat3res); +} + +ssize_t +xdr_to_fsinfo3args (struct iovec inmsg, fsinfo3args *fi) +{ +        return xdr_to_generic (inmsg, (void *)fi, +                                   (xdrproc_t)xdr_fsinfo3args); +} + + +ssize_t +xdr_serialize_fsinfo3res (struct iovec outmsg, fsinfo3res *res) +{ +        return xdr_serialize_generic (outmsg, (void *)res, +                                          (xdrproc_t)xdr_fsinfo3res); +} + + +ssize_t +xdr_to_pathconf3args (struct iovec inmsg, pathconf3args *pc) +{ +        return xdr_to_generic (inmsg, (void *)pc, +                                   (xdrproc_t)xdr_pathconf3args);} + + +ssize_t +xdr_serialize_pathconf3res (struct iovec outmsg, pathconf3res *res) +{ +        return xdr_serialize_generic (outmsg, (void *)res, +                                          (xdrproc_t)xdr_pathconf3res); +} + + +ssize_t +xdr_to_commit3args (struct iovec inmsg, commit3args *ca) +{ +        return xdr_to_generic (inmsg, (void *)ca, +                                   (xdrproc_t)xdr_commit3args); +} + + +ssize_t +xdr_serialize_commit3res (struct iovec outmsg, commit3res *res) +{ +        return xdr_serialize_generic (outmsg, (void *)res, +                                          (xdrproc_t)xdr_commit3res); +} + + +ssize_t +xdr_serialize_exports (struct iovec outmsg, exports *elist) +{ +        XDR     xdr; +        ssize_t  ret = -1; + +        if ((!outmsg.iov_base) || (!elist)) +                return -1; + +        xdrmem_create (&xdr, outmsg.iov_base, (unsigned int)outmsg.iov_len, +                       XDR_ENCODE); + +        if (!xdr_exports (&xdr, elist)) +                goto ret; + +        ret = xdr_decoded_length (xdr); + +ret: +        return ret; +} + + +ssize_t +xdr_serialize_nfsstat3 (struct iovec outmsg, nfsstat3 *s) +{ +        return xdr_serialize_generic (outmsg, (void *)s, +                                          (xdrproc_t)xdr_nfsstat3); +} + + diff --git a/rpc/xdr/src/msg-nfs3.h b/rpc/xdr/src/msg-nfs3.h new file mode 100644 index 00000000000..f0d57c64632 --- /dev/null +++ b/rpc/xdr/src/msg-nfs3.h @@ -0,0 +1,186 @@ +/* +  Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com> +  This file is part of GlusterFS. + +  GlusterFS is free software; you can redistribute it and/or modify +  it under the terms of the GNU Affero General Public License as published +  by the Free Software Foundation; either version 3 of the License, +  or (at your option) any later version. + +  GlusterFS is distributed in the hope that it will be useful, but +  WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +  Affero General Public License for more details. + +  You should have received a copy of the GNU Affero General Public License +  along with this program.  If not, see +  <http://www.gnu.org/licenses/>. +*/ + +#ifndef _MSG_NFS3_H_ +#define _MSG_NFS3_H_ + +#ifndef _CONFIG_H +#define _CONFIG_H +#include "config.h" +#endif + +#include "xdr-nfs3.h" + +#include <sys/types.h> +#include <sys/uio.h> + +extern ssize_t +xdr_to_mountpath (struct iovec outpath, struct iovec inmsg); + +extern ssize_t +xdr_serialize_mountres3 (struct iovec outmsg, mountres3 *res); + +extern ssize_t +xdr_serialize_mountbody (struct iovec outmsg, mountbody *mb); + +extern ssize_t +xdr_to_getattr3args (struct iovec inmsg, getattr3args *ga); + +extern ssize_t +xdr_serialize_getattr3res (struct iovec outmsg, getattr3res *res); + +extern ssize_t +xdr_serialize_setattr3res (struct iovec outmsg, setattr3res *res); + +extern ssize_t +xdr_to_setattr3args (struct iovec inmsg, setattr3args *sa); + +extern ssize_t +xdr_serialize_lookup3res (struct iovec outmsg, lookup3res *res); + +extern ssize_t +xdr_to_lookup3args (struct iovec inmsg, lookup3args *la); + +extern ssize_t +xdr_to_access3args (struct iovec inmsg, access3args *ac); + +extern ssize_t +xdr_serialize_access3res (struct iovec outmsg, access3res *res); + +extern ssize_t +xdr_to_readlink3args (struct iovec inmsg, readlink3args *ra); + +extern ssize_t +xdr_serialize_readlink3res (struct iovec outmsg, readlink3res *res); + +extern ssize_t +xdr_to_read3args (struct iovec inmsg, read3args *ra); + +extern ssize_t +xdr_serialize_read3res (struct iovec outmsg, read3res *res); + +extern ssize_t +xdr_serialize_read3res_nocopy (struct iovec outmsg, read3res *res); + +extern ssize_t +xdr_to_write3args (struct iovec inmsg, write3args *wa); + +extern ssize_t +xdr_to_write3args_nocopy (struct iovec inmsg, write3args *wa, +                          struct iovec *payload); + +extern ssize_t +xdr_serialize_write3res (struct iovec outmsg, write3res *res); + +extern ssize_t +xdr_to_create3args (struct iovec inmsg, create3args *ca); + +extern ssize_t +xdr_serialize_create3res (struct iovec outmsg, create3res *res); + +extern ssize_t +xdr_serialize_mkdir3res (struct iovec outmsg, mkdir3res *res); + +extern ssize_t +xdr_to_mkdir3args (struct iovec inmsg, mkdir3args *ma); + +extern ssize_t +xdr_to_symlink3args (struct iovec inmsg, symlink3args *sa); + +extern ssize_t +xdr_serialize_symlink3res (struct iovec outmsg, symlink3res *res); + +extern ssize_t +xdr_to_mknod3args (struct iovec inmsg, mknod3args *ma); + +extern ssize_t +xdr_serialize_mknod3res (struct iovec outmsg, mknod3res *res); + +extern ssize_t +xdr_to_remove3args (struct iovec inmsg, remove3args *ra); + +extern ssize_t +xdr_serialize_remove3res (struct iovec outmsg, remove3res *res); + +extern ssize_t +xdr_to_rmdir3args (struct iovec inmsg, rmdir3args *ra); + +extern ssize_t +xdr_serialize_rmdir3res (struct iovec outmsg, rmdir3res *res); + +extern ssize_t +xdr_serialize_rename3res (struct iovec outmsg, rename3res *res); + +extern ssize_t +xdr_to_rename3args (struct iovec inmsg, rename3args *ra); + +extern ssize_t +xdr_serialize_link3res (struct iovec outmsg, link3res *li); + +extern ssize_t +xdr_to_link3args (struct iovec inmsg, link3args *la); + +extern ssize_t +xdr_to_readdir3args (struct iovec inmsg, readdir3args *rd); + +extern ssize_t +xdr_serialize_readdir3res (struct iovec outmsg, readdir3res *res); + +extern ssize_t +xdr_to_readdirp3args (struct iovec inmsg, readdirp3args *rp); + +extern ssize_t +xdr_serialize_readdirp3res (struct iovec outmsg, readdirp3res *res); + +extern ssize_t +xdr_to_fsstat3args (struct iovec inmsg, fsstat3args *fa); + +extern ssize_t +xdr_serialize_fsstat3res (struct iovec outmsg, fsstat3res *res); + +extern ssize_t +xdr_to_fsinfo3args (struct iovec inmsg, fsinfo3args *fi); + +extern ssize_t +xdr_serialize_fsinfo3res (struct iovec outmsg, fsinfo3res *res); + +extern ssize_t +xdr_to_pathconf3args (struct iovec inmsg, pathconf3args *pc); + +extern ssize_t +xdr_serialize_pathconf3res (struct iovec outmsg, pathconf3res *res); + +extern ssize_t +xdr_to_commit3args (struct iovec inmsg, commit3args *ca); + +extern ssize_t +xdr_serialize_commit3res (struct iovec outmsg, commit3res *res); + +extern ssize_t +xdr_serialize_exports (struct iovec outmsg, exports *elist); + +extern ssize_t +xdr_serialize_mountlist (struct iovec outmsg, mountlist *ml); + +extern ssize_t +xdr_serialize_mountstat3 (struct iovec outmsg, mountstat3 *m); + +extern ssize_t +xdr_serialize_nfsstat3 (struct iovec outmsg, nfsstat3 *s); +#endif diff --git a/rpc/xdr/src/xdr-generic.c b/rpc/xdr/src/xdr-generic.c index f7e09482b45..caea7e9ce0d 100644 --- a/rpc/xdr/src/xdr-generic.c +++ b/rpc/xdr/src/xdr-generic.c @@ -96,3 +96,39 @@ xdr_to_generic_payload (struct iovec inmsg, void *args, xdrproc_t proc,  ret:          return ret;  } + +ssize_t +xdr_length_round_up (size_t len, size_t bufsize) +{ +        int     roundup = 0; + +        roundup = len % XDR_BYTES_PER_UNIT; +        if (roundup > 0) +                roundup = XDR_BYTES_PER_UNIT - roundup; + +        if ((roundup > 0) && ((roundup + len) <= bufsize)) +                len += roundup; + +        return len; +} + +int +xdr_bytes_round_up (struct iovec *vec, size_t bufsize) +{ +        vec->iov_len = xdr_length_round_up (vec->iov_len, bufsize); +        return 0; +} + + +void +xdr_vector_round_up (struct iovec *vec, int vcount, uint32_t count) +{ +        uint32_t round_count = 0; + +        round_count = xdr_length_round_up (count, 1048576); +        round_count -= count; +        if (round_count == 0) +                return; + +        vec[vcount-1].iov_len += round_count; +} diff --git a/rpc/xdr/src/xdr-generic.h b/rpc/xdr/src/xdr-generic.h index 9b8019637e3..963c6185b69 100644 --- a/rpc/xdr/src/xdr-generic.h +++ b/rpc/xdr/src/xdr-generic.h @@ -31,6 +31,7 @@  #define xdr_encoded_length(xdr) (((size_t)(&xdr)->x_private) - ((size_t)(&xdr)->x_base))  #define xdr_decoded_length(xdr) (((size_t)(&xdr)->x_private) - ((size_t)(&xdr)->x_base)) +#define XDR_BYTES_PER_UNIT      4  ssize_t  xdr_serialize_generic (struct iovec outmsg, void *res, xdrproc_t proc); @@ -42,4 +43,14 @@ ssize_t  xdr_to_generic_payload (struct iovec inmsg, void *args, xdrproc_t proc,                          struct iovec *pendingpayload); + +extern int +xdr_bytes_round_up (struct iovec *vec, size_t bufsize); + +extern ssize_t +xdr_length_round_up (size_t len, size_t bufsize); + +void +xdr_vector_round_up (struct iovec *vec, int vcount, uint32_t count); +  #endif /* !_XDR_GENERIC_H */ diff --git a/rpc/xdr/src/xdr-nfs3.c b/rpc/xdr/src/xdr-nfs3.c new file mode 100644 index 00000000000..febc6a69597 --- /dev/null +++ b/rpc/xdr/src/xdr-nfs3.c @@ -0,0 +1,1897 @@ +/* +  Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com> +  This file is part of GlusterFS. + +  GlusterFS is free software; you can redistribute it and/or modify +  it under the terms of the GNU Affero General Public License as published +  by the Free Software Foundation; either version 3 of the License, +  or (at your option) any later version. + +  GlusterFS is distributed in the hope that it will be useful, but +  WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +  Affero General Public License for more details. + +  You should have received a copy of the GNU Affero General Public License +  along with this program.  If not, see +  <http://www.gnu.org/licenses/>. +*/ + +#include "xdr-nfs3.h" +#include "mem-pool.h" + +#if GF_DARWIN_HOST_OS +#define xdr_u_quad_t xdr_u_int64_t +#define xdr_quad_t   xdr_int64_t +#define xdr_uint32_t xdr_u_int32_t +#endif + +bool_t +xdr_uint64 (XDR *xdrs, uint64 *objp) +{ +	 if (!xdr_uint64_t (xdrs, objp)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_int64 (XDR *xdrs, int64 *objp) +{ +	 if (!xdr_int64_t (xdrs, objp)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_uint32 (XDR *xdrs, uint32 *objp) +{ +	 if (!xdr_uint32_t (xdrs, objp)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_int32 (XDR *xdrs, int32 *objp) +{ +	 if (!xdr_int32_t (xdrs, objp)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_filename3 (XDR *xdrs, filename3 *objp) +{ +	 if (!xdr_string (xdrs, objp, ~0)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_nfspath3 (XDR *xdrs, nfspath3 *objp) +{ +	 if (!xdr_string (xdrs, objp, ~0)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_fileid3 (XDR *xdrs, fileid3 *objp) +{ +	 if (!xdr_uint64 (xdrs, objp)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_cookie3 (XDR *xdrs, cookie3 *objp) +{ +	 if (!xdr_uint64 (xdrs, objp)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_cookieverf3 (XDR *xdrs, cookieverf3 objp) +{ +	 if (!xdr_opaque (xdrs, objp, NFS3_COOKIEVERFSIZE)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_createverf3 (XDR *xdrs, createverf3 objp) +{ +	 if (!xdr_opaque (xdrs, objp, NFS3_CREATEVERFSIZE)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_writeverf3 (XDR *xdrs, writeverf3 objp) +{ +	 if (!xdr_opaque (xdrs, objp, NFS3_WRITEVERFSIZE)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_uid3 (XDR *xdrs, uid3 *objp) +{ +	 if (!xdr_uint32 (xdrs, objp)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_gid3 (XDR *xdrs, gid3 *objp) +{ +	 if (!xdr_uint32 (xdrs, objp)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_size3 (XDR *xdrs, size3 *objp) +{ +	 if (!xdr_uint64 (xdrs, objp)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_offset3 (XDR *xdrs, offset3 *objp) +{ +	 if (!xdr_uint64 (xdrs, objp)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_mode3 (XDR *xdrs, mode3 *objp) +{ +	 if (!xdr_uint32 (xdrs, objp)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_count3 (XDR *xdrs, count3 *objp) +{ +	 if (!xdr_uint32 (xdrs, objp)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_nfsstat3 (XDR *xdrs, nfsstat3 *objp) +{ +	 if (!xdr_enum (xdrs, (enum_t *) objp)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_ftype3 (XDR *xdrs, ftype3 *objp) +{ +	 if (!xdr_enum (xdrs, (enum_t *) objp)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_specdata3 (XDR *xdrs, specdata3 *objp) +{ +	 if (!xdr_uint32 (xdrs, &objp->specdata1)) +		 return FALSE; +	 if (!xdr_uint32 (xdrs, &objp->specdata2)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_nfs_fh3 (XDR *xdrs, nfs_fh3 *objp) +{ +	 if (!xdr_bytes (xdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, NFS3_FHSIZE)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_nfstime3 (XDR *xdrs, nfstime3 *objp) +{ +	 if (!xdr_uint32 (xdrs, &objp->seconds)) +		 return FALSE; +	 if (!xdr_uint32 (xdrs, &objp->nseconds)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_fattr3 (XDR *xdrs, fattr3 *objp) +{ +	 if (!xdr_ftype3 (xdrs, &objp->type)) +		 return FALSE; +	 if (!xdr_mode3 (xdrs, &objp->mode)) +		 return FALSE; +	 if (!xdr_uint32 (xdrs, &objp->nlink)) +		 return FALSE; +	 if (!xdr_uid3 (xdrs, &objp->uid)) +		 return FALSE; +	 if (!xdr_gid3 (xdrs, &objp->gid)) +		 return FALSE; +	 if (!xdr_size3 (xdrs, &objp->size)) +		 return FALSE; +	 if (!xdr_size3 (xdrs, &objp->used)) +		 return FALSE; +	 if (!xdr_specdata3 (xdrs, &objp->rdev)) +		 return FALSE; +	 if (!xdr_uint64 (xdrs, &objp->fsid)) +		 return FALSE; +	 if (!xdr_fileid3 (xdrs, &objp->fileid)) +		 return FALSE; +	 if (!xdr_nfstime3 (xdrs, &objp->atime)) +		 return FALSE; +	 if (!xdr_nfstime3 (xdrs, &objp->mtime)) +		 return FALSE; +	 if (!xdr_nfstime3 (xdrs, &objp->ctime)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_post_op_attr (XDR *xdrs, post_op_attr *objp) +{ +	 if (!xdr_bool (xdrs, &objp->attributes_follow)) +		 return FALSE; +	switch (objp->attributes_follow) { +	case TRUE: +		 if (!xdr_fattr3 (xdrs, &objp->post_op_attr_u.attributes)) +			 return FALSE; +		break; +	case FALSE: +		break; +	default: +		return FALSE; +	} +	return TRUE; +} + +bool_t +xdr_wcc_attr (XDR *xdrs, wcc_attr *objp) +{ +	 if (!xdr_size3 (xdrs, &objp->size)) +		 return FALSE; +	 if (!xdr_nfstime3 (xdrs, &objp->mtime)) +		 return FALSE; +	 if (!xdr_nfstime3 (xdrs, &objp->ctime)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_pre_op_attr (XDR *xdrs, pre_op_attr *objp) +{ +	 if (!xdr_bool (xdrs, &objp->attributes_follow)) +		 return FALSE; +	switch (objp->attributes_follow) { +	case TRUE: +		 if (!xdr_wcc_attr (xdrs, &objp->pre_op_attr_u.attributes)) +			 return FALSE; +		break; +	case FALSE: +		break; +	default: +		return FALSE; +	} +	return TRUE; +} + +bool_t +xdr_wcc_data (XDR *xdrs, wcc_data *objp) +{ +	 if (!xdr_pre_op_attr (xdrs, &objp->before)) +		 return FALSE; +	 if (!xdr_post_op_attr (xdrs, &objp->after)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_post_op_fh3 (XDR *xdrs, post_op_fh3 *objp) +{ +	 if (!xdr_bool (xdrs, &objp->handle_follows)) +		 return FALSE; +	switch (objp->handle_follows) { +	case TRUE: +		 if (!xdr_nfs_fh3 (xdrs, &objp->post_op_fh3_u.handle)) +			 return FALSE; +		break; +	case FALSE: +		break; +	default: +		return FALSE; +	} +	return TRUE; +} + +bool_t +xdr_time_how (XDR *xdrs, time_how *objp) +{ +	 if (!xdr_enum (xdrs, (enum_t *) objp)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_set_mode3 (XDR *xdrs, set_mode3 *objp) +{ +	 if (!xdr_bool (xdrs, &objp->set_it)) +		 return FALSE; +	switch (objp->set_it) { +	case TRUE: +		 if (!xdr_mode3 (xdrs, &objp->set_mode3_u.mode)) +			 return FALSE; +		break; +	default: +		break; +	} +	return TRUE; +} + +bool_t +xdr_set_uid3 (XDR *xdrs, set_uid3 *objp) +{ +	 if (!xdr_bool (xdrs, &objp->set_it)) +		 return FALSE; +	switch (objp->set_it) { +	case TRUE: +		 if (!xdr_uid3 (xdrs, &objp->set_uid3_u.uid)) +			 return FALSE; +		break; +	default: +		break; +	} +	return TRUE; +} + +bool_t +xdr_set_gid3 (XDR *xdrs, set_gid3 *objp) +{ +	 if (!xdr_bool (xdrs, &objp->set_it)) +		 return FALSE; +	switch (objp->set_it) { +	case TRUE: +		 if (!xdr_gid3 (xdrs, &objp->set_gid3_u.gid)) +			 return FALSE; +		break; +	default: +		break; +	} +	return TRUE; +} + +bool_t +xdr_set_size3 (XDR *xdrs, set_size3 *objp) +{ +	 if (!xdr_bool (xdrs, &objp->set_it)) +		 return FALSE; +	switch (objp->set_it) { +	case TRUE: +		 if (!xdr_size3 (xdrs, &objp->set_size3_u.size)) +			 return FALSE; +		break; +	default: +		break; +	} +	return TRUE; +} + +bool_t +xdr_set_atime (XDR *xdrs, set_atime *objp) +{ +	 if (!xdr_time_how (xdrs, &objp->set_it)) +		 return FALSE; +	switch (objp->set_it) { +	case SET_TO_CLIENT_TIME: +		 if (!xdr_nfstime3 (xdrs, &objp->set_atime_u.atime)) +			 return FALSE; +		break; +	default: +		break; +	} +	return TRUE; +} + +bool_t +xdr_set_mtime (XDR *xdrs, set_mtime *objp) +{ +	 if (!xdr_time_how (xdrs, &objp->set_it)) +		 return FALSE; +	switch (objp->set_it) { +	case SET_TO_CLIENT_TIME: +		 if (!xdr_nfstime3 (xdrs, &objp->set_mtime_u.mtime)) +			 return FALSE; +		break; +	default: +		break; +	} +	return TRUE; +} + +bool_t +xdr_sattr3 (XDR *xdrs, sattr3 *objp) +{ +	 if (!xdr_set_mode3 (xdrs, &objp->mode)) +		 return FALSE; +	 if (!xdr_set_uid3 (xdrs, &objp->uid)) +		 return FALSE; +	 if (!xdr_set_gid3 (xdrs, &objp->gid)) +		 return FALSE; +	 if (!xdr_set_size3 (xdrs, &objp->size)) +		 return FALSE; +	 if (!xdr_set_atime (xdrs, &objp->atime)) +		 return FALSE; +	 if (!xdr_set_mtime (xdrs, &objp->mtime)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_diropargs3 (XDR *xdrs, diropargs3 *objp) +{ +	 if (!xdr_nfs_fh3 (xdrs, &objp->dir)) +		 return FALSE; +	 if (!xdr_filename3 (xdrs, &objp->name)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_getattr3args (XDR *xdrs, getattr3args *objp) +{ +	 if (!xdr_nfs_fh3 (xdrs, &objp->object)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_getattr3resok (XDR *xdrs, getattr3resok *objp) +{ +	 if (!xdr_fattr3 (xdrs, &objp->obj_attributes)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_getattr3res (XDR *xdrs, getattr3res *objp) +{ +	 if (!xdr_nfsstat3 (xdrs, &objp->status)) +		 return FALSE; +	switch (objp->status) { +	case NFS3_OK: +		 if (!xdr_getattr3resok (xdrs, &objp->getattr3res_u.resok)) +			 return FALSE; +		break; +	default: +		break; +	} +	return TRUE; +} + +bool_t +xdr_sattrguard3 (XDR *xdrs, sattrguard3 *objp) +{ +	 if (!xdr_bool (xdrs, &objp->check)) +		 return FALSE; +	switch (objp->check) { +	case TRUE: +		 if (!xdr_nfstime3 (xdrs, &objp->sattrguard3_u.obj_ctime)) +			 return FALSE; +		break; +	case FALSE: +		break; +	default: +		return FALSE; +	} +	return TRUE; +} + +bool_t +xdr_setattr3args (XDR *xdrs, setattr3args *objp) +{ +	 if (!xdr_nfs_fh3 (xdrs, &objp->object)) +		 return FALSE; +	 if (!xdr_sattr3 (xdrs, &objp->new_attributes)) +		 return FALSE; +	 if (!xdr_sattrguard3 (xdrs, &objp->guard)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_setattr3resok (XDR *xdrs, setattr3resok *objp) +{ +	 if (!xdr_wcc_data (xdrs, &objp->obj_wcc)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_setattr3resfail (XDR *xdrs, setattr3resfail *objp) +{ +	 if (!xdr_wcc_data (xdrs, &objp->obj_wcc)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_setattr3res (XDR *xdrs, setattr3res *objp) +{ +	 if (!xdr_nfsstat3 (xdrs, &objp->status)) +		 return FALSE; +	switch (objp->status) { +	case NFS3_OK: +		 if (!xdr_setattr3resok (xdrs, &objp->setattr3res_u.resok)) +			 return FALSE; +		break; +	default: +		 if (!xdr_setattr3resfail (xdrs, &objp->setattr3res_u.resfail)) +			 return FALSE; +		break; +	} +	return TRUE; +} + +bool_t +xdr_lookup3args (XDR *xdrs, lookup3args *objp) +{ +	 if (!xdr_diropargs3 (xdrs, &objp->what)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_lookup3resok (XDR *xdrs, lookup3resok *objp) +{ +	 if (!xdr_nfs_fh3 (xdrs, &objp->object)) +		 return FALSE; +	 if (!xdr_post_op_attr (xdrs, &objp->obj_attributes)) +		 return FALSE; +	 if (!xdr_post_op_attr (xdrs, &objp->dir_attributes)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_lookup3resfail (XDR *xdrs, lookup3resfail *objp) +{ +	 if (!xdr_post_op_attr (xdrs, &objp->dir_attributes)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_lookup3res (XDR *xdrs, lookup3res *objp) +{ +	 if (!xdr_nfsstat3 (xdrs, &objp->status)) +		 return FALSE; +	switch (objp->status) { +	case NFS3_OK: +		 if (!xdr_lookup3resok (xdrs, &objp->lookup3res_u.resok)) +			 return FALSE; +		break; +	default: +		 if (!xdr_lookup3resfail (xdrs, &objp->lookup3res_u.resfail)) +			 return FALSE; +		break; +	} +	return TRUE; +} + +bool_t +xdr_access3args (XDR *xdrs, access3args *objp) +{ +	 if (!xdr_nfs_fh3 (xdrs, &objp->object)) +		 return FALSE; +	 if (!xdr_uint32 (xdrs, &objp->access)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_access3resok (XDR *xdrs, access3resok *objp) +{ +	 if (!xdr_post_op_attr (xdrs, &objp->obj_attributes)) +		 return FALSE; +	 if (!xdr_uint32 (xdrs, &objp->access)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_access3resfail (XDR *xdrs, access3resfail *objp) +{ +	 if (!xdr_post_op_attr (xdrs, &objp->obj_attributes)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_access3res (XDR *xdrs, access3res *objp) +{ +	 if (!xdr_nfsstat3 (xdrs, &objp->status)) +		 return FALSE; +	switch (objp->status) { +	case NFS3_OK: +		 if (!xdr_access3resok (xdrs, &objp->access3res_u.resok)) +			 return FALSE; +		break; +	default: +		 if (!xdr_access3resfail (xdrs, &objp->access3res_u.resfail)) +			 return FALSE; +		break; +	} +	return TRUE; +} + +bool_t +xdr_readlink3args (XDR *xdrs, readlink3args *objp) +{ +	 if (!xdr_nfs_fh3 (xdrs, &objp->symlink)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_readlink3resok (XDR *xdrs, readlink3resok *objp) +{ +	 if (!xdr_post_op_attr (xdrs, &objp->symlink_attributes)) +		 return FALSE; +	 if (!xdr_nfspath3 (xdrs, &objp->data)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_readlink3resfail (XDR *xdrs, readlink3resfail *objp) +{ +	 if (!xdr_post_op_attr (xdrs, &objp->symlink_attributes)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_readlink3res (XDR *xdrs, readlink3res *objp) +{ +	 if (!xdr_nfsstat3 (xdrs, &objp->status)) +		 return FALSE; +	switch (objp->status) { +	case NFS3_OK: +		 if (!xdr_readlink3resok (xdrs, &objp->readlink3res_u.resok)) +			 return FALSE; +		break; +	default: +		 if (!xdr_readlink3resfail (xdrs, &objp->readlink3res_u.resfail)) +			 return FALSE; +		break; +	} +	return TRUE; +} + +bool_t +xdr_read3args (XDR *xdrs, read3args *objp) +{ +	 if (!xdr_nfs_fh3 (xdrs, &objp->file)) +		 return FALSE; +	 if (!xdr_offset3 (xdrs, &objp->offset)) +		 return FALSE; +	 if (!xdr_count3 (xdrs, &objp->count)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_read3resok_nocopy (XDR *xdrs, read3resok *objp) +{ +	 if (!xdr_post_op_attr (xdrs, &objp->file_attributes)) +		 return FALSE; +	 if (!xdr_count3 (xdrs, &objp->count)) +		 return FALSE; +	 if (!xdr_bool (xdrs, &objp->eof)) +		 return FALSE; +         if (!xdr_u_int (xdrs, (u_int *) &objp->data.data_len)) +                 return FALSE; +	return TRUE; +} + + +bool_t +xdr_read3resok (XDR *xdrs, read3resok *objp) +{ +	 if (!xdr_post_op_attr (xdrs, &objp->file_attributes)) +		 return FALSE; +	 if (!xdr_count3 (xdrs, &objp->count)) +		 return FALSE; +	 if (!xdr_bool (xdrs, &objp->eof)) +		 return FALSE; +	 if (!xdr_bytes (xdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, ~0)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_read3resfail (XDR *xdrs, read3resfail *objp) +{ +	 if (!xdr_post_op_attr (xdrs, &objp->file_attributes)) +		 return FALSE; +	return TRUE; +} + + +bool_t +xdr_read3res_nocopy (XDR *xdrs, read3res *objp) +{ +	 if (!xdr_nfsstat3 (xdrs, &objp->status)) +		 return FALSE; +	switch (objp->status) { +	case NFS3_OK: +		 if (!xdr_read3resok_nocopy (xdrs, &objp->read3res_u.resok)) +			 return FALSE; +		break; +	default: +		 if (!xdr_read3resfail (xdrs, &objp->read3res_u.resfail)) +			 return FALSE; +		break; +	} +	return TRUE; +} + + +bool_t +xdr_read3res (XDR *xdrs, read3res *objp) +{ +	 if (!xdr_nfsstat3 (xdrs, &objp->status)) +		 return FALSE; +	switch (objp->status) { +	case NFS3_OK: +		 if (!xdr_read3resok (xdrs, &objp->read3res_u.resok)) +			 return FALSE; +		break; +	default: +		 if (!xdr_read3resfail (xdrs, &objp->read3res_u.resfail)) +			 return FALSE; +		break; +	} +	return TRUE; +} + +bool_t +xdr_stable_how (XDR *xdrs, stable_how *objp) +{ +	 if (!xdr_enum (xdrs, (enum_t *) objp)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_write3args (XDR *xdrs, write3args *objp) +{ +	 if (!xdr_nfs_fh3 (xdrs, &objp->file)) +		 return FALSE; +	 if (!xdr_offset3 (xdrs, &objp->offset)) +		 return FALSE; +	 if (!xdr_count3 (xdrs, &objp->count)) +		 return FALSE; +	 if (!xdr_stable_how (xdrs, &objp->stable)) +		 return FALSE; + +         /* Added specifically to avoid copies from the xdr buffer into +          * the write3args structure, which will also require an already +          * allocated buffer. That is not optimal. +          */ +         if (!xdr_u_int (xdrs, (u_int *) &objp->data.data_len)) +                 return FALSE; + +         /* The remaining bytes in the xdr buffer are the bytes that need to be +          * written. See how these bytes are extracted in the xdr_to_write3args +          * code path. Be careful, while using the write3args structure, since +          * only the data.data_len has been filled. The actual data is +          * extracted in xdr_to_write3args path. +          */ + +         /*	 if (!xdr_bytes (xdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, ~0)) +		 return FALSE; +                 */ +	return TRUE; +} + +bool_t +xdr_write3resok (XDR *xdrs, write3resok *objp) +{ +	 if (!xdr_wcc_data (xdrs, &objp->file_wcc)) +		 return FALSE; +	 if (!xdr_count3 (xdrs, &objp->count)) +		 return FALSE; +	 if (!xdr_stable_how (xdrs, &objp->committed)) +		 return FALSE; +	 if (!xdr_writeverf3 (xdrs, objp->verf)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_write3resfail (XDR *xdrs, write3resfail *objp) +{ +	 if (!xdr_wcc_data (xdrs, &objp->file_wcc)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_write3res (XDR *xdrs, write3res *objp) +{ +	 if (!xdr_nfsstat3 (xdrs, &objp->status)) +		 return FALSE; +	switch (objp->status) { +	case NFS3_OK: +		 if (!xdr_write3resok (xdrs, &objp->write3res_u.resok)) +			 return FALSE; +		break; +	default: +		 if (!xdr_write3resfail (xdrs, &objp->write3res_u.resfail)) +			 return FALSE; +		break; +	} +	return TRUE; +} + +bool_t +xdr_createmode3 (XDR *xdrs, createmode3 *objp) +{ +	 if (!xdr_enum (xdrs, (enum_t *) objp)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_createhow3 (XDR *xdrs, createhow3 *objp) +{ +	 if (!xdr_createmode3 (xdrs, &objp->mode)) +		 return FALSE; +	switch (objp->mode) { +	case UNCHECKED: +	case GUARDED: +		 if (!xdr_sattr3 (xdrs, &objp->createhow3_u.obj_attributes)) +			 return FALSE; +		break; +	case EXCLUSIVE: +		 if (!xdr_createverf3 (xdrs, objp->createhow3_u.verf)) +			 return FALSE; +		break; +	default: +		return FALSE; +	} +	return TRUE; +} + +bool_t +xdr_create3args (XDR *xdrs, create3args *objp) +{ +	 if (!xdr_diropargs3 (xdrs, &objp->where)) +		 return FALSE; +	 if (!xdr_createhow3 (xdrs, &objp->how)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_create3resok (XDR *xdrs, create3resok *objp) +{ +	 if (!xdr_post_op_fh3 (xdrs, &objp->obj)) +		 return FALSE; +	 if (!xdr_post_op_attr (xdrs, &objp->obj_attributes)) +		 return FALSE; +	 if (!xdr_wcc_data (xdrs, &objp->dir_wcc)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_create3resfail (XDR *xdrs, create3resfail *objp) +{ +	 if (!xdr_wcc_data (xdrs, &objp->dir_wcc)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_create3res (XDR *xdrs, create3res *objp) +{ +	 if (!xdr_nfsstat3 (xdrs, &objp->status)) +		 return FALSE; +	switch (objp->status) { +	case NFS3_OK: +		 if (!xdr_create3resok (xdrs, &objp->create3res_u.resok)) +			 return FALSE; +		break; +	default: +		 if (!xdr_create3resfail (xdrs, &objp->create3res_u.resfail)) +			 return FALSE; +		break; +	} +	return TRUE; +} + +bool_t +xdr_mkdir3args (XDR *xdrs, mkdir3args *objp) +{ +	 if (!xdr_diropargs3 (xdrs, &objp->where)) +		 return FALSE; +	 if (!xdr_sattr3 (xdrs, &objp->attributes)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_mkdir3resok (XDR *xdrs, mkdir3resok *objp) +{ +	 if (!xdr_post_op_fh3 (xdrs, &objp->obj)) +		 return FALSE; +	 if (!xdr_post_op_attr (xdrs, &objp->obj_attributes)) +		 return FALSE; +	 if (!xdr_wcc_data (xdrs, &objp->dir_wcc)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_mkdir3resfail (XDR *xdrs, mkdir3resfail *objp) +{ +	 if (!xdr_wcc_data (xdrs, &objp->dir_wcc)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_mkdir3res (XDR *xdrs, mkdir3res *objp) +{ +	 if (!xdr_nfsstat3 (xdrs, &objp->status)) +		 return FALSE; +	switch (objp->status) { +	case NFS3_OK: +		 if (!xdr_mkdir3resok (xdrs, &objp->mkdir3res_u.resok)) +			 return FALSE; +		break; +	default: +		 if (!xdr_mkdir3resfail (xdrs, &objp->mkdir3res_u.resfail)) +			 return FALSE; +		break; +	} +	return TRUE; +} + +bool_t +xdr_symlinkdata3 (XDR *xdrs, symlinkdata3 *objp) +{ +	 if (!xdr_sattr3 (xdrs, &objp->symlink_attributes)) +		 return FALSE; +	 if (!xdr_nfspath3 (xdrs, &objp->symlink_data)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_symlink3args (XDR *xdrs, symlink3args *objp) +{ +	 if (!xdr_diropargs3 (xdrs, &objp->where)) +		 return FALSE; +	 if (!xdr_symlinkdata3 (xdrs, &objp->symlink)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_symlink3resok (XDR *xdrs, symlink3resok *objp) +{ +	 if (!xdr_post_op_fh3 (xdrs, &objp->obj)) +		 return FALSE; +	 if (!xdr_post_op_attr (xdrs, &objp->obj_attributes)) +		 return FALSE; +	 if (!xdr_wcc_data (xdrs, &objp->dir_wcc)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_symlink3resfail (XDR *xdrs, symlink3resfail *objp) +{ +	 if (!xdr_wcc_data (xdrs, &objp->dir_wcc)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_symlink3res (XDR *xdrs, symlink3res *objp) +{ +	 if (!xdr_nfsstat3 (xdrs, &objp->status)) +		 return FALSE; +	switch (objp->status) { +	case NFS3_OK: +		 if (!xdr_symlink3resok (xdrs, &objp->symlink3res_u.resok)) +			 return FALSE; +		break; +	default: +		 if (!xdr_symlink3resfail (xdrs, &objp->symlink3res_u.resfail)) +			 return FALSE; +		break; +	} +	return TRUE; +} + +bool_t +xdr_devicedata3 (XDR *xdrs, devicedata3 *objp) +{ +	 if (!xdr_sattr3 (xdrs, &objp->dev_attributes)) +		 return FALSE; +	 if (!xdr_specdata3 (xdrs, &objp->spec)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_mknoddata3 (XDR *xdrs, mknoddata3 *objp) +{ +	 if (!xdr_ftype3 (xdrs, &objp->type)) +		 return FALSE; +	switch (objp->type) { +	case NF3CHR: +	case NF3BLK: +		 if (!xdr_devicedata3 (xdrs, &objp->mknoddata3_u.device)) +			 return FALSE; +		break; +	case NF3SOCK: +	case NF3FIFO: +		 if (!xdr_sattr3 (xdrs, &objp->mknoddata3_u.pipe_attributes)) +			 return FALSE; +		break; +	default: +		break; +	} +	return TRUE; +} + +bool_t +xdr_mknod3args (XDR *xdrs, mknod3args *objp) +{ +	 if (!xdr_diropargs3 (xdrs, &objp->where)) +		 return FALSE; +	 if (!xdr_mknoddata3 (xdrs, &objp->what)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_mknod3resok (XDR *xdrs, mknod3resok *objp) +{ +	 if (!xdr_post_op_fh3 (xdrs, &objp->obj)) +		 return FALSE; +	 if (!xdr_post_op_attr (xdrs, &objp->obj_attributes)) +		 return FALSE; +	 if (!xdr_wcc_data (xdrs, &objp->dir_wcc)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_mknod3resfail (XDR *xdrs, mknod3resfail *objp) +{ +	 if (!xdr_wcc_data (xdrs, &objp->dir_wcc)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_mknod3res (XDR *xdrs, mknod3res *objp) +{ +	 if (!xdr_nfsstat3 (xdrs, &objp->status)) +		 return FALSE; +	switch (objp->status) { +	case NFS3_OK: +		 if (!xdr_mknod3resok (xdrs, &objp->mknod3res_u.resok)) +			 return FALSE; +		break; +	default: +		 if (!xdr_mknod3resfail (xdrs, &objp->mknod3res_u.resfail)) +			 return FALSE; +		break; +	} +	return TRUE; +} + +bool_t +xdr_remove3args (XDR *xdrs, remove3args *objp) +{ +	 if (!xdr_diropargs3 (xdrs, &objp->object)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_remove3resok (XDR *xdrs, remove3resok *objp) +{ +	 if (!xdr_wcc_data (xdrs, &objp->dir_wcc)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_remove3resfail (XDR *xdrs, remove3resfail *objp) +{ +	 if (!xdr_wcc_data (xdrs, &objp->dir_wcc)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_remove3res (XDR *xdrs, remove3res *objp) +{ +	 if (!xdr_nfsstat3 (xdrs, &objp->status)) +		 return FALSE; +	switch (objp->status) { +	case NFS3_OK: +		 if (!xdr_remove3resok (xdrs, &objp->remove3res_u.resok)) +			 return FALSE; +		break; +	default: +		 if (!xdr_remove3resfail (xdrs, &objp->remove3res_u.resfail)) +			 return FALSE; +		break; +	} +	return TRUE; +} + +bool_t +xdr_rmdir3args (XDR *xdrs, rmdir3args *objp) +{ +	 if (!xdr_diropargs3 (xdrs, &objp->object)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_rmdir3resok (XDR *xdrs, rmdir3resok *objp) +{ +	 if (!xdr_wcc_data (xdrs, &objp->dir_wcc)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_rmdir3resfail (XDR *xdrs, rmdir3resfail *objp) +{ +	 if (!xdr_wcc_data (xdrs, &objp->dir_wcc)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_rmdir3res (XDR *xdrs, rmdir3res *objp) +{ +	 if (!xdr_nfsstat3 (xdrs, &objp->status)) +		 return FALSE; +	switch (objp->status) { +	case NFS3_OK: +		 if (!xdr_rmdir3resok (xdrs, &objp->rmdir3res_u.resok)) +			 return FALSE; +		break; +	default: +		 if (!xdr_rmdir3resfail (xdrs, &objp->rmdir3res_u.resfail)) +			 return FALSE; +		break; +	} +	return TRUE; +} + +bool_t +xdr_rename3args (XDR *xdrs, rename3args *objp) +{ +	 if (!xdr_diropargs3 (xdrs, &objp->from)) +		 return FALSE; +	 if (!xdr_diropargs3 (xdrs, &objp->to)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_rename3resok (XDR *xdrs, rename3resok *objp) +{ +	 if (!xdr_wcc_data (xdrs, &objp->fromdir_wcc)) +		 return FALSE; +	 if (!xdr_wcc_data (xdrs, &objp->todir_wcc)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_rename3resfail (XDR *xdrs, rename3resfail *objp) +{ +	 if (!xdr_wcc_data (xdrs, &objp->fromdir_wcc)) +		 return FALSE; +	 if (!xdr_wcc_data (xdrs, &objp->todir_wcc)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_rename3res (XDR *xdrs, rename3res *objp) +{ +	 if (!xdr_nfsstat3 (xdrs, &objp->status)) +		 return FALSE; +	switch (objp->status) { +	case NFS3_OK: +		 if (!xdr_rename3resok (xdrs, &objp->rename3res_u.resok)) +			 return FALSE; +		break; +	default: +		 if (!xdr_rename3resfail (xdrs, &objp->rename3res_u.resfail)) +			 return FALSE; +		break; +	} +	return TRUE; +} + +bool_t +xdr_link3args (XDR *xdrs, link3args *objp) +{ +	 if (!xdr_nfs_fh3 (xdrs, &objp->file)) +		 return FALSE; +	 if (!xdr_diropargs3 (xdrs, &objp->link)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_link3resok (XDR *xdrs, link3resok *objp) +{ +	 if (!xdr_post_op_attr (xdrs, &objp->file_attributes)) +		 return FALSE; +	 if (!xdr_wcc_data (xdrs, &objp->linkdir_wcc)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_link3resfail (XDR *xdrs, link3resfail *objp) +{ +	 if (!xdr_post_op_attr (xdrs, &objp->file_attributes)) +		 return FALSE; +	 if (!xdr_wcc_data (xdrs, &objp->linkdir_wcc)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_link3res (XDR *xdrs, link3res *objp) +{ +	 if (!xdr_nfsstat3 (xdrs, &objp->status)) +		 return FALSE; +	switch (objp->status) { +	case NFS3_OK: +		 if (!xdr_link3resok (xdrs, &objp->link3res_u.resok)) +			 return FALSE; +		break; +	default: +		 if (!xdr_link3resfail (xdrs, &objp->link3res_u.resfail)) +			 return FALSE; +		break; +	} +	return TRUE; +} + +bool_t +xdr_readdir3args (XDR *xdrs, readdir3args *objp) +{ +	 if (!xdr_nfs_fh3 (xdrs, &objp->dir)) +		 return FALSE; +	 if (!xdr_cookie3 (xdrs, &objp->cookie)) +		 return FALSE; +	 if (!xdr_cookieverf3 (xdrs, objp->cookieverf)) +		 return FALSE; +	 if (!xdr_count3 (xdrs, &objp->count)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_entry3 (XDR *xdrs, entry3 *objp) +{ +	 if (!xdr_fileid3 (xdrs, &objp->fileid)) +		 return FALSE; +	 if (!xdr_filename3 (xdrs, &objp->name)) +		 return FALSE; +	 if (!xdr_cookie3 (xdrs, &objp->cookie)) +		 return FALSE; +	 if (!xdr_pointer (xdrs, (char **)&objp->nextentry, sizeof (entry3), (xdrproc_t) xdr_entry3)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_dirlist3 (XDR *xdrs, dirlist3 *objp) +{ +	 if (!xdr_pointer (xdrs, (char **)&objp->entries, sizeof (entry3), (xdrproc_t) xdr_entry3)) +		 return FALSE; +	 if (!xdr_bool (xdrs, &objp->eof)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_readdir3resok (XDR *xdrs, readdir3resok *objp) +{ +	 if (!xdr_post_op_attr (xdrs, &objp->dir_attributes)) +		 return FALSE; +	 if (!xdr_cookieverf3 (xdrs, objp->cookieverf)) +		 return FALSE; +	 if (!xdr_dirlist3 (xdrs, &objp->reply)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_readdir3resfail (XDR *xdrs, readdir3resfail *objp) +{ +	 if (!xdr_post_op_attr (xdrs, &objp->dir_attributes)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_readdir3res (XDR *xdrs, readdir3res *objp) +{ +	 if (!xdr_nfsstat3 (xdrs, &objp->status)) +		 return FALSE; +	switch (objp->status) { +	case NFS3_OK: +		 if (!xdr_readdir3resok (xdrs, &objp->readdir3res_u.resok)) +			 return FALSE; +		break; +	default: +		 if (!xdr_readdir3resfail (xdrs, &objp->readdir3res_u.resfail)) +			 return FALSE; +		break; +	} +	return TRUE; +} + +bool_t +xdr_readdirp3args (XDR *xdrs, readdirp3args *objp) +{ +	 if (!xdr_nfs_fh3 (xdrs, &objp->dir)) +		 return FALSE; +	 if (!xdr_cookie3 (xdrs, &objp->cookie)) +		 return FALSE; +	 if (!xdr_cookieverf3 (xdrs, objp->cookieverf)) +		 return FALSE; +	 if (!xdr_count3 (xdrs, &objp->dircount)) +		 return FALSE; +	 if (!xdr_count3 (xdrs, &objp->maxcount)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_entryp3 (XDR *xdrs, entryp3 *objp) +{ +	 if (!xdr_fileid3 (xdrs, &objp->fileid)) +		 return FALSE; +	 if (!xdr_filename3 (xdrs, &objp->name)) +		 return FALSE; +	 if (!xdr_cookie3 (xdrs, &objp->cookie)) +		 return FALSE; +	 if (!xdr_post_op_attr (xdrs, &objp->name_attributes)) +		 return FALSE; +	 if (!xdr_post_op_fh3 (xdrs, &objp->name_handle)) +		 return FALSE; +	 if (!xdr_pointer (xdrs, (char **)&objp->nextentry, sizeof (entryp3), (xdrproc_t) xdr_entryp3)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_dirlistp3 (XDR *xdrs, dirlistp3 *objp) +{ +	 if (!xdr_pointer (xdrs, (char **)&objp->entries, sizeof (entryp3), (xdrproc_t) xdr_entryp3)) +		 return FALSE; +	 if (!xdr_bool (xdrs, &objp->eof)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_readdirp3resok (XDR *xdrs, readdirp3resok *objp) +{ +	 if (!xdr_post_op_attr (xdrs, &objp->dir_attributes)) +		 return FALSE; +	 if (!xdr_cookieverf3 (xdrs, objp->cookieverf)) +		 return FALSE; +	 if (!xdr_dirlistp3 (xdrs, &objp->reply)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_readdirp3resfail (XDR *xdrs, readdirp3resfail *objp) +{ +	 if (!xdr_post_op_attr (xdrs, &objp->dir_attributes)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_readdirp3res (XDR *xdrs, readdirp3res *objp) +{ +	 if (!xdr_nfsstat3 (xdrs, &objp->status)) +		 return FALSE; +	switch (objp->status) { +	case NFS3_OK: +		 if (!xdr_readdirp3resok (xdrs, &objp->readdirp3res_u.resok)) +			 return FALSE; +		break; +	default: +		 if (!xdr_readdirp3resfail (xdrs, &objp->readdirp3res_u.resfail)) +			 return FALSE; +		break; +	} +	return TRUE; +} + +bool_t +xdr_fsstat3args (XDR *xdrs, fsstat3args *objp) +{ +	 if (!xdr_nfs_fh3 (xdrs, &objp->fsroot)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_fsstat3resok (XDR *xdrs, fsstat3resok *objp) +{ +	 if (!xdr_post_op_attr (xdrs, &objp->obj_attributes)) +		 return FALSE; +	 if (!xdr_size3 (xdrs, &objp->tbytes)) +		 return FALSE; +	 if (!xdr_size3 (xdrs, &objp->fbytes)) +		 return FALSE; +	 if (!xdr_size3 (xdrs, &objp->abytes)) +		 return FALSE; +	 if (!xdr_size3 (xdrs, &objp->tfiles)) +		 return FALSE; +	 if (!xdr_size3 (xdrs, &objp->ffiles)) +		 return FALSE; +	 if (!xdr_size3 (xdrs, &objp->afiles)) +		 return FALSE; +	 if (!xdr_uint32 (xdrs, &objp->invarsec)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_fsstat3resfail (XDR *xdrs, fsstat3resfail *objp) +{ +	 if (!xdr_post_op_attr (xdrs, &objp->obj_attributes)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_fsstat3res (XDR *xdrs, fsstat3res *objp) +{ +	 if (!xdr_nfsstat3 (xdrs, &objp->status)) +		 return FALSE; +	switch (objp->status) { +	case NFS3_OK: +		 if (!xdr_fsstat3resok (xdrs, &objp->fsstat3res_u.resok)) +			 return FALSE; +		break; +	default: +		 if (!xdr_fsstat3resfail (xdrs, &objp->fsstat3res_u.resfail)) +			 return FALSE; +		break; +	} +	return TRUE; +} + +bool_t +xdr_fsinfo3args (XDR *xdrs, fsinfo3args *objp) +{ +	 if (!xdr_nfs_fh3 (xdrs, &objp->fsroot)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_fsinfo3resok (XDR *xdrs, fsinfo3resok *objp) +{ +	 if (!xdr_post_op_attr (xdrs, &objp->obj_attributes)) +		 return FALSE; +	 if (!xdr_uint32 (xdrs, &objp->rtmax)) +		 return FALSE; +	 if (!xdr_uint32 (xdrs, &objp->rtpref)) +		 return FALSE; +	 if (!xdr_uint32 (xdrs, &objp->rtmult)) +		 return FALSE; +	 if (!xdr_uint32 (xdrs, &objp->wtmax)) +		 return FALSE; +	 if (!xdr_uint32 (xdrs, &objp->wtpref)) +		 return FALSE; +	 if (!xdr_uint32 (xdrs, &objp->wtmult)) +		 return FALSE; +	 if (!xdr_uint32 (xdrs, &objp->dtpref)) +		 return FALSE; +	 if (!xdr_size3 (xdrs, &objp->maxfilesize)) +		 return FALSE; +	 if (!xdr_nfstime3 (xdrs, &objp->time_delta)) +		 return FALSE; +	 if (!xdr_uint32 (xdrs, &objp->properties)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_fsinfo3resfail (XDR *xdrs, fsinfo3resfail *objp) +{ +	 if (!xdr_post_op_attr (xdrs, &objp->obj_attributes)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_fsinfo3res (XDR *xdrs, fsinfo3res *objp) +{ +	 if (!xdr_nfsstat3 (xdrs, &objp->status)) +		 return FALSE; +	switch (objp->status) { +	case NFS3_OK: +		 if (!xdr_fsinfo3resok (xdrs, &objp->fsinfo3res_u.resok)) +			 return FALSE; +		break; +	default: +		 if (!xdr_fsinfo3resfail (xdrs, &objp->fsinfo3res_u.resfail)) +			 return FALSE; +		break; +	} +	return TRUE; +} + +bool_t +xdr_pathconf3args (XDR *xdrs, pathconf3args *objp) +{ +	 if (!xdr_nfs_fh3 (xdrs, &objp->object)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_pathconf3resok (XDR *xdrs, pathconf3resok *objp) +{ +	register int32_t *buf; + + +	if (xdrs->x_op == XDR_ENCODE) { +		 if (!xdr_post_op_attr (xdrs, &objp->obj_attributes)) +			 return FALSE; +		 if (!xdr_uint32 (xdrs, &objp->linkmax)) +			 return FALSE; +		 if (!xdr_uint32 (xdrs, &objp->name_max)) +			 return FALSE; +		buf = XDR_INLINE (xdrs, 4 * BYTES_PER_XDR_UNIT); +		if (buf == NULL) { +			 if (!xdr_bool (xdrs, &objp->no_trunc)) +				 return FALSE; +			 if (!xdr_bool (xdrs, &objp->chown_restricted)) +				 return FALSE; +			 if (!xdr_bool (xdrs, &objp->case_insensitive)) +				 return FALSE; +			 if (!xdr_bool (xdrs, &objp->case_preserving)) +				 return FALSE; +		} else { +			IXDR_PUT_BOOL(buf, objp->no_trunc); +			IXDR_PUT_BOOL(buf, objp->chown_restricted); +			IXDR_PUT_BOOL(buf, objp->case_insensitive); +			IXDR_PUT_BOOL(buf, objp->case_preserving); +		} +		return TRUE; +	} else if (xdrs->x_op == XDR_DECODE) { +		 if (!xdr_post_op_attr (xdrs, &objp->obj_attributes)) +			 return FALSE; +		 if (!xdr_uint32 (xdrs, &objp->linkmax)) +			 return FALSE; +		 if (!xdr_uint32 (xdrs, &objp->name_max)) +			 return FALSE; +		buf = XDR_INLINE (xdrs, 4 * BYTES_PER_XDR_UNIT); +		if (buf == NULL) { +			 if (!xdr_bool (xdrs, &objp->no_trunc)) +				 return FALSE; +			 if (!xdr_bool (xdrs, &objp->chown_restricted)) +				 return FALSE; +			 if (!xdr_bool (xdrs, &objp->case_insensitive)) +				 return FALSE; +			 if (!xdr_bool (xdrs, &objp->case_preserving)) +				 return FALSE; +		} else { +			objp->no_trunc = IXDR_GET_BOOL(buf); +			objp->chown_restricted = IXDR_GET_BOOL(buf); +			objp->case_insensitive = IXDR_GET_BOOL(buf); +			objp->case_preserving = IXDR_GET_BOOL(buf); +		} +	 return TRUE; +	} + +	 if (!xdr_post_op_attr (xdrs, &objp->obj_attributes)) +		 return FALSE; +	 if (!xdr_uint32 (xdrs, &objp->linkmax)) +		 return FALSE; +	 if (!xdr_uint32 (xdrs, &objp->name_max)) +		 return FALSE; +	 if (!xdr_bool (xdrs, &objp->no_trunc)) +		 return FALSE; +	 if (!xdr_bool (xdrs, &objp->chown_restricted)) +		 return FALSE; +	 if (!xdr_bool (xdrs, &objp->case_insensitive)) +		 return FALSE; +	 if (!xdr_bool (xdrs, &objp->case_preserving)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_pathconf3resfail (XDR *xdrs, pathconf3resfail *objp) +{ +	 if (!xdr_post_op_attr (xdrs, &objp->obj_attributes)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_pathconf3res (XDR *xdrs, pathconf3res *objp) +{ +	 if (!xdr_nfsstat3 (xdrs, &objp->status)) +		 return FALSE; +	switch (objp->status) { +	case NFS3_OK: +		 if (!xdr_pathconf3resok (xdrs, &objp->pathconf3res_u.resok)) +			 return FALSE; +		break; +	default: +		 if (!xdr_pathconf3resfail (xdrs, &objp->pathconf3res_u.resfail)) +			 return FALSE; +		break; +	} +	return TRUE; +} + +bool_t +xdr_commit3args (XDR *xdrs, commit3args *objp) +{ +	 if (!xdr_nfs_fh3 (xdrs, &objp->file)) +		 return FALSE; +	 if (!xdr_offset3 (xdrs, &objp->offset)) +		 return FALSE; +	 if (!xdr_count3 (xdrs, &objp->count)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_commit3resok (XDR *xdrs, commit3resok *objp) +{ +	 if (!xdr_wcc_data (xdrs, &objp->file_wcc)) +		 return FALSE; +	 if (!xdr_writeverf3 (xdrs, objp->verf)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_commit3resfail (XDR *xdrs, commit3resfail *objp) +{ +	 if (!xdr_wcc_data (xdrs, &objp->file_wcc)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_commit3res (XDR *xdrs, commit3res *objp) +{ +	 if (!xdr_nfsstat3 (xdrs, &objp->status)) +		 return FALSE; +	switch (objp->status) { +	case NFS3_OK: +		 if (!xdr_commit3resok (xdrs, &objp->commit3res_u.resok)) +			 return FALSE; +		break; +	default: +		 if (!xdr_commit3resfail (xdrs, &objp->commit3res_u.resfail)) +			 return FALSE; +		break; +	} +	return TRUE; +} + +bool_t +xdr_fhandle3 (XDR *xdrs, fhandle3 *objp) +{ +	 if (!xdr_bytes (xdrs, (char **)&objp->fhandle3_val, (u_int *) &objp->fhandle3_len, FHSIZE3)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_dirpath (XDR *xdrs, dirpath *objp) +{ +	 if (!xdr_string (xdrs, objp, MNTPATHLEN)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_name (XDR *xdrs, name *objp) +{ +	 if (!xdr_string (xdrs, objp, MNTNAMLEN)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_mountstat3 (XDR *xdrs, mountstat3 *objp) +{ +	 if (!xdr_enum (xdrs, (enum_t *) objp)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_mountres3_ok (XDR *xdrs, mountres3_ok *objp) +{ +	 if (!xdr_fhandle3 (xdrs, &objp->fhandle)) +		 return FALSE; +	 if (!xdr_array (xdrs, (char **)&objp->auth_flavors.auth_flavors_val, (u_int *) &objp->auth_flavors.auth_flavors_len, ~0, +		sizeof (int), (xdrproc_t) xdr_int)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_mountres3 (XDR *xdrs, mountres3 *objp) +{ +	 if (!xdr_mountstat3 (xdrs, &objp->fhs_status)) +		 return FALSE; +	switch (objp->fhs_status) { +	case MNT3_OK: +		 if (!xdr_mountres3_ok (xdrs, &objp->mountres3_u.mountinfo)) +			 return FALSE; +		break; +	default: +		break; +	} +	return TRUE; +} + +bool_t +xdr_mountlist (XDR *xdrs, mountlist *objp) +{ +	 if (!xdr_pointer (xdrs, (char **)objp, sizeof (struct mountbody), (xdrproc_t) xdr_mountbody)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_mountbody (XDR *xdrs, mountbody *objp) +{ +	 if (!xdr_name (xdrs, &objp->ml_hostname)) +		 return FALSE; +	 if (!xdr_dirpath (xdrs, &objp->ml_directory)) +		 return FALSE; +	 if (!xdr_mountlist (xdrs, &objp->ml_next)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_groups (XDR *xdrs, groups *objp) +{ +	 if (!xdr_pointer (xdrs, (char **)objp, sizeof (struct groupnode), (xdrproc_t) xdr_groupnode)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_groupnode (XDR *xdrs, groupnode *objp) +{ +	 if (!xdr_name (xdrs, &objp->gr_name)) +		 return FALSE; +	 if (!xdr_groups (xdrs, &objp->gr_next)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_exports (XDR *xdrs, exports *objp) +{ +	 if (!xdr_pointer (xdrs, (char **)objp, sizeof (struct exportnode), (xdrproc_t) xdr_exportnode)) +		 return FALSE; +	return TRUE; +} + +bool_t +xdr_exportnode (XDR *xdrs, exportnode *objp) +{ +	 if (!xdr_dirpath (xdrs, &objp->ex_dir)) +		 return FALSE; +	 if (!xdr_groups (xdrs, &objp->ex_groups)) +		 return FALSE; +	 if (!xdr_exports (xdrs, &objp->ex_next)) +		 return FALSE; +	return TRUE; +} + +void +xdr_free_exports_list (struct exportnode *first) +{ +        struct exportnode       *elist = NULL; + +        if (!first) +                return; + +        while (first) { +                elist = first->ex_next; +                if (first->ex_dir) +                        GF_FREE (first->ex_dir); + +                if (first->ex_groups) { +                        if (first->ex_groups->gr_name) +                                GF_FREE (first->ex_groups->gr_name); +                        GF_FREE (first->ex_groups); +                } + +                GF_FREE (first); +                first = elist; +        } + +} + + +void +xdr_free_mountlist (mountlist ml) +{ +        struct mountbody        *next = NULL; + +        if (!ml) +                return; + +        while (ml) { +                GF_FREE (ml->ml_hostname); +                GF_FREE (ml->ml_directory); +                next = ml->ml_next; +                GF_FREE (ml); +                ml = next; +        } + +        return; +} + + +/* Free statements are based on the way sunrpc xdr decoding + * code performs memory allocations. + */ +void +xdr_free_write3args_nocopy (write3args *wa) +{ +        if (!wa) +                return; + +        FREE (wa->file.data.data_val); +} + + diff --git a/rpc/xdr/src/xdr-nfs3.h b/rpc/xdr/src/xdr-nfs3.h new file mode 100644 index 00000000000..0530876a8de --- /dev/null +++ b/rpc/xdr/src/xdr-nfs3.h @@ -0,0 +1,1206 @@ +/* +  Copyright (c) 2010 Gluster, Inc. <http://www.gluster.com> +  This file is part of GlusterFS. + +  GlusterFS is free software; you can redistribute it and/or modify +  it under the terms of the GNU Affero General Public License as published +  by the Free Software Foundation; either version 3 of the License, +  or (at your option) any later version. + +  GlusterFS is distributed in the hope that it will be useful, but +  WITHOUT ANY WARRANTY; without even the implied warranty of +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU +  Affero General Public License for more details. + +  You should have received a copy of the GNU Affero General Public License +  along with this program.  If not, see +  <http://www.gnu.org/licenses/>. +*/ + +#ifndef _XDR_NFS3_H +#define _XDR_NFS3_H + +#include <rpc/rpc.h> +#include <sys/types.h> + +#define NFS3_FHSIZE             64 +#define NFS3_COOKIEVERFSIZE     8 +#define NFS3_CREATEVERFSIZE     8 +#define NFS3_WRITEVERFSIZE      8 + +#define NFS3_ENTRY3_FIXED_SIZE  24 +#define NFS3_POSTOPATTR_SIZE    88 +#define NFS3_READDIR_RESOK_SIZE (NFS3_POSTOPATTR_SIZE + sizeof (bool_t) + NFS3_COOKIEVERFSIZE) + +/* In size of post_op_fh3, the length of the file handle will have to be + * included separately since we have variable length fh. Here we only account + * for the field for handle_follows and for the file handle length field. + */ +#define NFS3_POSTOPFH3_FIXED_SIZE     (sizeof (bool_t) + sizeof (uint32_t)) + +/* Similarly, the size of the entry will have to include the variable length + * file handle and the length of the entry name. + */ +#define NFS3_ENTRYP3_FIXED_SIZE  (NFS3_ENTRY3_FIXED_SIZE + NFS3_POSTOPATTR_SIZE + NFS3_POSTOPFH3_FIXED_SIZE) + +typedef uint64_t uint64; +typedef int64_t int64; +typedef uint32_t uint32; +typedef int32_t int32; +typedef char *filename3; +typedef char *nfspath3; +typedef uint64 fileid3; +typedef uint64 cookie3; +typedef char cookieverf3[NFS3_COOKIEVERFSIZE]; +typedef char createverf3[NFS3_CREATEVERFSIZE]; +typedef char writeverf3[NFS3_WRITEVERFSIZE]; +typedef uint32 uid3; +typedef uint32 gid3; +typedef uint64 size3; +typedef uint64 offset3; +typedef uint32 mode3; +typedef uint32 count3; + +#define NFS3MODE_SETXUID        0x00800 +#define NFS3MODE_SETXGID        0x00400 +#define NFS3MODE_SAVESWAPTXT    0x00200 +#define NFS3MODE_ROWNER         0x00100 +#define NFS3MODE_WOWNER         0x00080 +#define NFS3MODE_XOWNER         0x00040 +#define NFS3MODE_RGROUP         0x00020 +#define NFS3MODE_WGROUP         0x00010 +#define NFS3MODE_XGROUP         0x00008 +#define NFS3MODE_ROTHER         0x00004 +#define NFS3MODE_WOTHER         0x00002 +#define NFS3MODE_XOTHER         0x00001 + +enum nfsstat3 { +	NFS3_OK = 0, +	NFS3ERR_PERM = 1, +	NFS3ERR_NOENT = 2, +	NFS3ERR_IO = 5, +	NFS3ERR_NXIO = 6, +	NFS3ERR_ACCES = 13, +	NFS3ERR_EXIST = 17, +	NFS3ERR_XDEV = 18, +	NFS3ERR_NODEV = 19, +	NFS3ERR_NOTDIR = 20, +	NFS3ERR_ISDIR = 21, +	NFS3ERR_INVAL = 22, +	NFS3ERR_FBIG = 27, +	NFS3ERR_NOSPC = 28, +	NFS3ERR_ROFS = 30, +	NFS3ERR_MLINK = 31, +	NFS3ERR_NAMETOOLONG = 63, +	NFS3ERR_NOTEMPTY = 66, +	NFS3ERR_DQUOT = 69, +	NFS3ERR_STALE = 70, +	NFS3ERR_REMOTE = 71, +	NFS3ERR_BADHANDLE = 10001, +	NFS3ERR_NOT_SYNC = 10002, +	NFS3ERR_BAD_COOKIE = 10003, +	NFS3ERR_NOTSUPP = 10004, +	NFS3ERR_TOOSMALL = 10005, +	NFS3ERR_SERVERFAULT = 10006, +	NFS3ERR_BADTYPE = 10007, +	NFS3ERR_JUKEBOX = 10008, +}; +typedef enum nfsstat3 nfsstat3; + +enum ftype3 { +	NF3REG = 1, +	NF3DIR = 2, +	NF3BLK = 3, +	NF3CHR = 4, +	NF3LNK = 5, +	NF3SOCK = 6, +	NF3FIFO = 7, +}; +typedef enum ftype3 ftype3; + +struct specdata3 { +	uint32 specdata1; +	uint32 specdata2; +}; +typedef struct specdata3 specdata3; + +struct nfs_fh3 { +	struct { +		u_int data_len; +		char *data_val; +	} data; +}; +typedef struct nfs_fh3 nfs_fh3; + +struct nfstime3 { +	uint32 seconds; +	uint32 nseconds; +}; +typedef struct nfstime3 nfstime3; + +struct fattr3 { +	ftype3 type; +	mode3 mode; +	uint32 nlink; +	uid3 uid; +	gid3 gid; +	size3 size; +	size3 used; +	specdata3 rdev; +	uint64 fsid; +	fileid3 fileid; +	nfstime3 atime; +	nfstime3 mtime; +	nfstime3 ctime; +}; +typedef struct fattr3 fattr3; + +struct post_op_attr { +	bool_t attributes_follow; +	union { +		fattr3 attributes; +	} post_op_attr_u; +}; +typedef struct post_op_attr post_op_attr; + +struct wcc_attr { +	size3 size; +	nfstime3 mtime; +	nfstime3 ctime; +}; +typedef struct wcc_attr wcc_attr; + +struct pre_op_attr { +	bool_t attributes_follow; +	union { +		wcc_attr attributes; +	} pre_op_attr_u; +}; +typedef struct pre_op_attr pre_op_attr; + +struct wcc_data { +	pre_op_attr before; +	post_op_attr after; +}; +typedef struct wcc_data wcc_data; + +struct post_op_fh3 { +	bool_t handle_follows; +	union { +		nfs_fh3 handle; +	} post_op_fh3_u; +}; +typedef struct post_op_fh3 post_op_fh3; + +enum time_how { +	DONT_CHANGE = 0, +	SET_TO_SERVER_TIME = 1, +	SET_TO_CLIENT_TIME = 2, +}; +typedef enum time_how time_how; + +struct set_mode3 { +	bool_t set_it; +	union { +		mode3 mode; +	} set_mode3_u; +}; +typedef struct set_mode3 set_mode3; + +struct set_uid3 { +	bool_t set_it; +	union { +		uid3 uid; +	} set_uid3_u; +}; +typedef struct set_uid3 set_uid3; + +struct set_gid3 { +	bool_t set_it; +	union { +		gid3 gid; +	} set_gid3_u; +}; +typedef struct set_gid3 set_gid3; + +struct set_size3 { +	bool_t set_it; +	union { +		size3 size; +	} set_size3_u; +}; +typedef struct set_size3 set_size3; + +struct set_atime { +	time_how set_it; +	union { +		nfstime3 atime; +	} set_atime_u; +}; +typedef struct set_atime set_atime; + +struct set_mtime { +	time_how set_it; +	union { +		nfstime3 mtime; +	} set_mtime_u; +}; +typedef struct set_mtime set_mtime; + +struct sattr3 { +	set_mode3 mode; +	set_uid3 uid; +	set_gid3 gid; +	set_size3 size; +	set_atime atime; +	set_mtime mtime; +}; +typedef struct sattr3 sattr3; + +struct diropargs3 { +	nfs_fh3 dir; +	filename3 name; +}; +typedef struct diropargs3 diropargs3; + +struct getattr3args { +	nfs_fh3 object; +}; +typedef struct getattr3args getattr3args; + +struct getattr3resok { +	fattr3 obj_attributes; +}; +typedef struct getattr3resok getattr3resok; + +struct getattr3res { +	nfsstat3 status; +	union { +		getattr3resok resok; +	} getattr3res_u; +}; +typedef struct getattr3res getattr3res; + +struct sattrguard3 { +	bool_t check; +	union { +		nfstime3 obj_ctime; +	} sattrguard3_u; +}; +typedef struct sattrguard3 sattrguard3; + +struct setattr3args { +	nfs_fh3 object; +	sattr3 new_attributes; +	sattrguard3 guard; +}; +typedef struct setattr3args setattr3args; + +struct setattr3resok { +	wcc_data obj_wcc; +}; +typedef struct setattr3resok setattr3resok; + +struct setattr3resfail { +	wcc_data obj_wcc; +}; +typedef struct setattr3resfail setattr3resfail; + +struct setattr3res { +	nfsstat3 status; +	union { +		setattr3resok resok; +		setattr3resfail resfail; +	} setattr3res_u; +}; +typedef struct setattr3res setattr3res; + +struct lookup3args { +	diropargs3 what; +}; +typedef struct lookup3args lookup3args; + +struct lookup3resok { +	nfs_fh3 object; +	post_op_attr obj_attributes; +	post_op_attr dir_attributes; +}; +typedef struct lookup3resok lookup3resok; + +struct lookup3resfail { +	post_op_attr dir_attributes; +}; +typedef struct lookup3resfail lookup3resfail; + +struct lookup3res { +	nfsstat3 status; +	union { +		lookup3resok resok; +		lookup3resfail resfail; +	} lookup3res_u; +}; +typedef struct lookup3res lookup3res; +#define ACCESS3_READ 0x0001 +#define ACCESS3_LOOKUP 0x0002 +#define ACCESS3_MODIFY 0x0004 +#define ACCESS3_EXTEND 0x0008 +#define ACCESS3_DELETE 0x0010 +#define ACCESS3_EXECUTE 0x0020 + +struct access3args { +	nfs_fh3 object; +	uint32 access; +}; +typedef struct access3args access3args; + +struct access3resok { +	post_op_attr obj_attributes; +	uint32 access; +}; +typedef struct access3resok access3resok; + +struct access3resfail { +	post_op_attr obj_attributes; +}; +typedef struct access3resfail access3resfail; + +struct access3res { +	nfsstat3 status; +	union { +		access3resok resok; +		access3resfail resfail; +	} access3res_u; +}; +typedef struct access3res access3res; + +struct readlink3args { +	nfs_fh3 symlink; +}; +typedef struct readlink3args readlink3args; + +struct readlink3resok { +	post_op_attr symlink_attributes; +	nfspath3 data; +}; +typedef struct readlink3resok readlink3resok; + +struct readlink3resfail { +	post_op_attr symlink_attributes; +}; +typedef struct readlink3resfail readlink3resfail; + +struct readlink3res { +	nfsstat3 status; +	union { +		readlink3resok resok; +		readlink3resfail resfail; +	} readlink3res_u; +}; +typedef struct readlink3res readlink3res; + +struct read3args { +	nfs_fh3 file; +	offset3 offset; +	count3 count; +}; +typedef struct read3args read3args; + +struct read3resok { +	post_op_attr file_attributes; +	count3 count; +	bool_t eof; +	struct { +		u_int data_len; +		char *data_val; +	} data; +}; +typedef struct read3resok read3resok; + +struct read3resfail { +	post_op_attr file_attributes; +}; +typedef struct read3resfail read3resfail; + +struct read3res { +	nfsstat3 status; +	union { +		read3resok resok; +		read3resfail resfail; +	} read3res_u; +}; +typedef struct read3res read3res; + +enum stable_how { +	UNSTABLE = 0, +	DATA_SYNC = 1, +	FILE_SYNC = 2, +}; +typedef enum stable_how stable_how; + +struct write3args { +	nfs_fh3 file; +	offset3 offset; +	count3 count; +	stable_how stable; +	struct { +		u_int data_len; +		char *data_val; +	} data; +}; +typedef struct write3args write3args; + +/* Generally, the protocol allows the file handle to be less than 64 bytes but + * our server does not return file handles less than 64b so we can safely say + * sizeof (nfs_fh3) rather than first trying to extract the fh size of the + * network followed by a sized-read of the file handle. + */ +#define NFS3_WRITE3ARGS_SIZE    (sizeof (uint32_t) + NFS3_FHSIZE + sizeof (offset3) + sizeof (count3) + sizeof (uint32_t)) +struct write3resok { +	wcc_data file_wcc; +	count3 count; +	stable_how committed; +	writeverf3 verf; +}; +typedef struct write3resok write3resok; + +struct write3resfail { +	wcc_data file_wcc; +}; +typedef struct write3resfail write3resfail; + +struct write3res { +	nfsstat3 status; +	union { +		write3resok resok; +		write3resfail resfail; +	} write3res_u; +}; +typedef struct write3res write3res; + +enum createmode3 { +	UNCHECKED = 0, +	GUARDED = 1, +	EXCLUSIVE = 2, +}; +typedef enum createmode3 createmode3; + +struct createhow3 { +	createmode3 mode; +	union { +		sattr3 obj_attributes; +		createverf3 verf; +	} createhow3_u; +}; +typedef struct createhow3 createhow3; + +struct create3args { +	diropargs3 where; +	createhow3 how; +}; +typedef struct create3args create3args; + +struct create3resok { +	post_op_fh3 obj; +	post_op_attr obj_attributes; +	wcc_data dir_wcc; +}; +typedef struct create3resok create3resok; + +struct create3resfail { +	wcc_data dir_wcc; +}; +typedef struct create3resfail create3resfail; + +struct create3res { +	nfsstat3 status; +	union { +		create3resok resok; +		create3resfail resfail; +	} create3res_u; +}; +typedef struct create3res create3res; + +struct mkdir3args { +	diropargs3 where; +	sattr3 attributes; +}; +typedef struct mkdir3args mkdir3args; + +struct mkdir3resok { +	post_op_fh3 obj; +	post_op_attr obj_attributes; +	wcc_data dir_wcc; +}; +typedef struct mkdir3resok mkdir3resok; + +struct mkdir3resfail { +	wcc_data dir_wcc; +}; +typedef struct mkdir3resfail mkdir3resfail; + +struct mkdir3res { +	nfsstat3 status; +	union { +		mkdir3resok resok; +		mkdir3resfail resfail; +	} mkdir3res_u; +}; +typedef struct mkdir3res mkdir3res; + +struct symlinkdata3 { +	sattr3 symlink_attributes; +	nfspath3 symlink_data; +}; +typedef struct symlinkdata3 symlinkdata3; + +struct symlink3args { +	diropargs3 where; +	symlinkdata3 symlink; +}; +typedef struct symlink3args symlink3args; + +struct symlink3resok { +	post_op_fh3 obj; +	post_op_attr obj_attributes; +	wcc_data dir_wcc; +}; +typedef struct symlink3resok symlink3resok; + +struct symlink3resfail { +	wcc_data dir_wcc; +}; +typedef struct symlink3resfail symlink3resfail; + +struct symlink3res { +	nfsstat3 status; +	union { +		symlink3resok resok; +		symlink3resfail resfail; +	} symlink3res_u; +}; +typedef struct symlink3res symlink3res; + +struct devicedata3 { +	sattr3 dev_attributes; +	specdata3 spec; +}; +typedef struct devicedata3 devicedata3; + +struct mknoddata3 { +	ftype3 type; +	union { +		devicedata3 device; +		sattr3 pipe_attributes; +	} mknoddata3_u; +}; +typedef struct mknoddata3 mknoddata3; + +struct mknod3args { +	diropargs3 where; +	mknoddata3 what; +}; +typedef struct mknod3args mknod3args; + +struct mknod3resok { +	post_op_fh3 obj; +	post_op_attr obj_attributes; +	wcc_data dir_wcc; +}; +typedef struct mknod3resok mknod3resok; + +struct mknod3resfail { +	wcc_data dir_wcc; +}; +typedef struct mknod3resfail mknod3resfail; + +struct mknod3res { +	nfsstat3 status; +	union { +		mknod3resok resok; +		mknod3resfail resfail; +	} mknod3res_u; +}; +typedef struct mknod3res mknod3res; + +struct remove3args { +	diropargs3 object; +}; +typedef struct remove3args remove3args; + +struct remove3resok { +	wcc_data dir_wcc; +}; +typedef struct remove3resok remove3resok; + +struct remove3resfail { +	wcc_data dir_wcc; +}; +typedef struct remove3resfail remove3resfail; + +struct remove3res { +	nfsstat3 status; +	union { +		remove3resok resok; +		remove3resfail resfail; +	} remove3res_u; +}; +typedef struct remove3res remove3res; + +struct rmdir3args { +	diropargs3 object; +}; +typedef struct rmdir3args rmdir3args; + +struct rmdir3resok { +	wcc_data dir_wcc; +}; +typedef struct rmdir3resok rmdir3resok; + +struct rmdir3resfail { +	wcc_data dir_wcc; +}; +typedef struct rmdir3resfail rmdir3resfail; + +struct rmdir3res { +	nfsstat3 status; +	union { +		rmdir3resok resok; +		rmdir3resfail resfail; +	} rmdir3res_u; +}; +typedef struct rmdir3res rmdir3res; + +struct rename3args { +	diropargs3 from; +	diropargs3 to; +}; +typedef struct rename3args rename3args; + +struct rename3resok { +	wcc_data fromdir_wcc; +	wcc_data todir_wcc; +}; +typedef struct rename3resok rename3resok; + +struct rename3resfail { +	wcc_data fromdir_wcc; +	wcc_data todir_wcc; +}; +typedef struct rename3resfail rename3resfail; + +struct rename3res { +	nfsstat3 status; +	union { +		rename3resok resok; +		rename3resfail resfail; +	} rename3res_u; +}; +typedef struct rename3res rename3res; + +struct link3args { +	nfs_fh3 file; +	diropargs3 link; +}; +typedef struct link3args link3args; + +struct link3resok { +	post_op_attr file_attributes; +	wcc_data linkdir_wcc; +}; +typedef struct link3resok link3resok; + +struct link3resfail { +	post_op_attr file_attributes; +	wcc_data linkdir_wcc; +}; +typedef struct link3resfail link3resfail; + +struct link3res { +	nfsstat3 status; +	union { +		link3resok resok; +		link3resfail resfail; +	} link3res_u; +}; +typedef struct link3res link3res; + +struct readdir3args { +	nfs_fh3 dir; +	cookie3 cookie; +	cookieverf3 cookieverf; +	count3 count; +}; +typedef struct readdir3args readdir3args; + +struct entry3 { +	fileid3 fileid; +	filename3 name; +	cookie3 cookie; +	struct entry3 *nextentry; +}; +typedef struct entry3 entry3; + +struct dirlist3 { +	entry3 *entries; +	bool_t eof; +}; +typedef struct dirlist3 dirlist3; + +struct readdir3resok { +	post_op_attr dir_attributes; +	cookieverf3 cookieverf; +	dirlist3 reply; +}; +typedef struct readdir3resok readdir3resok; + +struct readdir3resfail { +	post_op_attr dir_attributes; +}; +typedef struct readdir3resfail readdir3resfail; + +struct readdir3res { +	nfsstat3 status; +	union { +		readdir3resok resok; +		readdir3resfail resfail; +	} readdir3res_u; +}; +typedef struct readdir3res readdir3res; + +struct readdirp3args { +	nfs_fh3 dir; +	cookie3 cookie; +	cookieverf3 cookieverf; +	count3 dircount; +	count3 maxcount; +}; +typedef struct readdirp3args readdirp3args; + +struct entryp3 { +	fileid3 fileid; +	filename3 name; +	cookie3 cookie; +	post_op_attr name_attributes; +	post_op_fh3 name_handle; +	struct entryp3 *nextentry; +}; +typedef struct entryp3 entryp3; + +struct dirlistp3 { +	entryp3 *entries; +	bool_t eof; +}; +typedef struct dirlistp3 dirlistp3; + +struct readdirp3resok { +	post_op_attr dir_attributes; +	cookieverf3 cookieverf; +	dirlistp3   reply; +}; +typedef struct readdirp3resok readdirp3resok; + +struct readdirp3resfail { +	post_op_attr dir_attributes; +}; +typedef struct readdirp3resfail readdirp3resfail; + +struct readdirp3res { +	nfsstat3 status; +	union { +		readdirp3resok resok; +		readdirp3resfail resfail; +	} readdirp3res_u; +}; +typedef struct readdirp3res readdirp3res; + +struct fsstat3args { +	nfs_fh3 fsroot; +}; +typedef struct fsstat3args fsstat3args; + +struct fsstat3resok { +	post_op_attr obj_attributes; +	size3 tbytes; +	size3 fbytes; +	size3 abytes; +	size3 tfiles; +	size3 ffiles; +	size3 afiles; +	uint32 invarsec; +}; +typedef struct fsstat3resok fsstat3resok; + +struct fsstat3resfail { +	post_op_attr obj_attributes; +}; +typedef struct fsstat3resfail fsstat3resfail; + +struct fsstat3res { +	nfsstat3 status; +	union { +		fsstat3resok resok; +		fsstat3resfail resfail; +	} fsstat3res_u; +}; +typedef struct fsstat3res fsstat3res; +#define FSF3_LINK 0x0001 +#define FSF3_SYMLINK 0x0002 +#define FSF3_HOMOGENEOUS 0x0008 +#define FSF3_CANSETTIME 0x0010 + +struct fsinfo3args { +	nfs_fh3 fsroot; +}; +typedef struct fsinfo3args fsinfo3args; + +struct fsinfo3resok { +	post_op_attr obj_attributes; +	uint32 rtmax; +	uint32 rtpref; +	uint32 rtmult; +	uint32 wtmax; +	uint32 wtpref; +	uint32 wtmult; +	uint32 dtpref; +	size3 maxfilesize; +	nfstime3 time_delta; +	uint32 properties; +}; +typedef struct fsinfo3resok fsinfo3resok; + +struct fsinfo3resfail { +	post_op_attr obj_attributes; +}; +typedef struct fsinfo3resfail fsinfo3resfail; + +struct fsinfo3res { +	nfsstat3 status; +	union { +		fsinfo3resok resok; +		fsinfo3resfail resfail; +	} fsinfo3res_u; +}; +typedef struct fsinfo3res fsinfo3res; + +struct pathconf3args { +	nfs_fh3 object; +}; +typedef struct pathconf3args pathconf3args; + +struct pathconf3resok { +	post_op_attr obj_attributes; +	uint32 linkmax; +	uint32 name_max; +	bool_t no_trunc; +	bool_t chown_restricted; +	bool_t case_insensitive; +	bool_t case_preserving; +}; +typedef struct pathconf3resok pathconf3resok; + +struct pathconf3resfail { +	post_op_attr obj_attributes; +}; +typedef struct pathconf3resfail pathconf3resfail; + +struct pathconf3res { +	nfsstat3 status; +	union { +		pathconf3resok resok; +		pathconf3resfail resfail; +	} pathconf3res_u; +}; +typedef struct pathconf3res pathconf3res; + +struct commit3args { +	nfs_fh3 file; +	offset3 offset; +	count3 count; +}; +typedef struct commit3args commit3args; + +struct commit3resok { +	wcc_data file_wcc; +	writeverf3 verf; +}; +typedef struct commit3resok commit3resok; + +struct commit3resfail { +	wcc_data file_wcc; +}; +typedef struct commit3resfail commit3resfail; + +struct commit3res { +	nfsstat3 status; +	union { +		commit3resok resok; +		commit3resfail resfail; +	} commit3res_u; +}; +typedef struct commit3res commit3res; +#define MNTPATHLEN 1024 +#define MNTNAMLEN 255 +#define FHSIZE3 NFS3_FHSIZE + +typedef struct { +	u_int fhandle3_len; +	char *fhandle3_val; +} fhandle3; + +typedef char *dirpath; + +typedef char *name; + +enum mountstat3 { +	MNT3_OK = 0, +	MNT3ERR_PERM = 1, +	MNT3ERR_NOENT = 2, +	MNT3ERR_IO = 5, +	MNT3ERR_ACCES = 13, +	MNT3ERR_NOTDIR = 20, +	MNT3ERR_INVAL = 22, +	MNT3ERR_NAMETOOLONG = 63, +	MNT3ERR_NOTSUPP = 10004, +	MNT3ERR_SERVERFAULT = 10006, +}; +typedef enum mountstat3 mountstat3; + +struct mountres3_ok { +	fhandle3 fhandle; +	struct { +		u_int auth_flavors_len; +		int *auth_flavors_val; +	} auth_flavors; +}; +typedef struct mountres3_ok mountres3_ok; + +struct mountres3 { +	mountstat3 fhs_status; +	union { +		mountres3_ok mountinfo; +	} mountres3_u; +}; +typedef struct mountres3 mountres3; + +typedef struct mountbody *mountlist; + +struct mountbody { +	name ml_hostname; +	dirpath ml_directory; +	mountlist ml_next; +}; +typedef struct mountbody mountbody; + +typedef struct groupnode *groups; + +struct groupnode { +	name gr_name; +	groups gr_next; +}; +typedef struct groupnode groupnode; + +typedef struct exportnode *exports; + +struct exportnode { +	dirpath ex_dir; +	groups ex_groups; +	exports ex_next; +}; +typedef struct exportnode exportnode; + +#define NFS_PROGRAM             100003 +#define NFS_V3                  3 + +#define NFS3_NULL               0 +#define NFS3_GETATTR            1 +#define NFS3_SETATTR            2 +#define NFS3_LOOKUP             3 +#define NFS3_ACCESS             4 +#define NFS3_READLINK           5 +#define NFS3_READ               6 +#define NFS3_WRITE              7 +#define NFS3_CREATE             8 +#define NFS3_MKDIR              9 +#define NFS3_SYMLINK            10 +#define NFS3_MKNOD              11 +#define NFS3_REMOVE             12 +#define NFS3_RMDIR              13 +#define NFS3_RENAME             14 +#define NFS3_LINK               15 +#define NFS3_READDIR            16 +#define NFS3_READDIRP           17 +#define NFS3_FSSTAT             18 +#define NFS3_FSINFO             19 +#define NFS3_PATHCONF           20 +#define NFS3_COMMIT             21 +#define NFS3_PROC_COUNT         22 + +#define MOUNT_PROGRAM           100005 +#define MOUNT_V3                3 +#define MOUNT_V1                1 + +#define MOUNT3_NULL             0 +#define MOUNT3_MNT              1 +#define MOUNT3_DUMP             2 +#define MOUNT3_UMNT             3 +#define MOUNT3_UMNTALL          4 +#define MOUNT3_EXPORT           5 +#define MOUNT3_PROC_COUNT       6 + +#define MOUNT1_NULL             0 +#define MOUNT1_DUMP             2 +#define MOUNT1_UMNT             3 +#define MOUNT1_EXPORT           5 +#define MOUNT1_PROC_COUNT       6 +/* the xdr functions */ + +extern  bool_t xdr_uint64 (XDR *, uint64*); +extern  bool_t xdr_int64 (XDR *, int64*); +extern  bool_t xdr_uint32 (XDR *, uint32*); +extern  bool_t xdr_int32 (XDR *, int32*); +extern  bool_t xdr_filename3 (XDR *, filename3*); +extern  bool_t xdr_nfspath3 (XDR *, nfspath3*); +extern  bool_t xdr_fileid3 (XDR *, fileid3*); +extern  bool_t xdr_cookie3 (XDR *, cookie3*); +extern  bool_t xdr_cookieverf3 (XDR *, cookieverf3); +extern  bool_t xdr_createverf3 (XDR *, createverf3); +extern  bool_t xdr_writeverf3 (XDR *, writeverf3); +extern  bool_t xdr_uid3 (XDR *, uid3*); +extern  bool_t xdr_gid3 (XDR *, gid3*); +extern  bool_t xdr_size3 (XDR *, size3*); +extern  bool_t xdr_offset3 (XDR *, offset3*); +extern  bool_t xdr_mode3 (XDR *, mode3*); +extern  bool_t xdr_count3 (XDR *, count3*); +extern  bool_t xdr_nfsstat3 (XDR *, nfsstat3*); +extern  bool_t xdr_ftype3 (XDR *, ftype3*); +extern  bool_t xdr_specdata3 (XDR *, specdata3*); +extern  bool_t xdr_nfs_fh3 (XDR *, nfs_fh3*); +extern  bool_t xdr_nfstime3 (XDR *, nfstime3*); +extern  bool_t xdr_fattr3 (XDR *, fattr3*); +extern  bool_t xdr_post_op_attr (XDR *, post_op_attr*); +extern  bool_t xdr_wcc_attr (XDR *, wcc_attr*); +extern  bool_t xdr_pre_op_attr (XDR *, pre_op_attr*); +extern  bool_t xdr_wcc_data (XDR *, wcc_data*); +extern  bool_t xdr_post_op_fh3 (XDR *, post_op_fh3*); +extern  bool_t xdr_time_how (XDR *, time_how*); +extern  bool_t xdr_set_mode3 (XDR *, set_mode3*); +extern  bool_t xdr_set_uid3 (XDR *, set_uid3*); +extern  bool_t xdr_set_gid3 (XDR *, set_gid3*); +extern  bool_t xdr_set_size3 (XDR *, set_size3*); +extern  bool_t xdr_set_atime (XDR *, set_atime*); +extern  bool_t xdr_set_mtime (XDR *, set_mtime*); +extern  bool_t xdr_sattr3 (XDR *, sattr3*); +extern  bool_t xdr_diropargs3 (XDR *, diropargs3*); +extern  bool_t xdr_getattr3args (XDR *, getattr3args*); +extern  bool_t xdr_getattr3resok (XDR *, getattr3resok*); +extern  bool_t xdr_getattr3res (XDR *, getattr3res*); +extern  bool_t xdr_sattrguard3 (XDR *, sattrguard3*); +extern  bool_t xdr_setattr3args (XDR *, setattr3args*); +extern  bool_t xdr_setattr3resok (XDR *, setattr3resok*); +extern  bool_t xdr_setattr3resfail (XDR *, setattr3resfail*); +extern  bool_t xdr_setattr3res (XDR *, setattr3res*); +extern  bool_t xdr_lookup3args (XDR *, lookup3args*); +extern  bool_t xdr_lookup3resok (XDR *, lookup3resok*); +extern  bool_t xdr_lookup3resfail (XDR *, lookup3resfail*); +extern  bool_t xdr_lookup3res (XDR *, lookup3res*); +extern  bool_t xdr_access3args (XDR *, access3args*); +extern  bool_t xdr_access3resok (XDR *, access3resok*); +extern  bool_t xdr_access3resfail (XDR *, access3resfail*); +extern  bool_t xdr_access3res (XDR *, access3res*); +extern  bool_t xdr_readlink3args (XDR *, readlink3args*); +extern  bool_t xdr_readlink3resok (XDR *, readlink3resok*); +extern  bool_t xdr_readlink3resfail (XDR *, readlink3resfail*); +extern  bool_t xdr_readlink3res (XDR *, readlink3res*); +extern  bool_t xdr_read3args (XDR *, read3args*); +extern  bool_t xdr_read3resok (XDR *, read3resok*); +extern  bool_t xdr_read3resfail (XDR *, read3resfail*); +extern  bool_t xdr_read3res (XDR *, read3res*); +extern  bool_t xdr_read3res_nocopy (XDR *xdrs, read3res *objp); +extern  bool_t xdr_stable_how (XDR *, stable_how*); +extern  bool_t xdr_write3args (XDR *, write3args*); +extern  bool_t xdr_write3resok (XDR *, write3resok*); +extern  bool_t xdr_write3resfail (XDR *, write3resfail*); +extern  bool_t xdr_write3res (XDR *, write3res*); +extern  bool_t xdr_createmode3 (XDR *, createmode3*); +extern  bool_t xdr_createhow3 (XDR *, createhow3*); +extern  bool_t xdr_create3args (XDR *, create3args*); +extern  bool_t xdr_create3resok (XDR *, create3resok*); +extern  bool_t xdr_create3resfail (XDR *, create3resfail*); +extern  bool_t xdr_create3res (XDR *, create3res*); +extern  bool_t xdr_mkdir3args (XDR *, mkdir3args*); +extern  bool_t xdr_mkdir3resok (XDR *, mkdir3resok*); +extern  bool_t xdr_mkdir3resfail (XDR *, mkdir3resfail*); +extern  bool_t xdr_mkdir3res (XDR *, mkdir3res*); +extern  bool_t xdr_symlinkdata3 (XDR *, symlinkdata3*); +extern  bool_t xdr_symlink3args (XDR *, symlink3args*); +extern  bool_t xdr_symlink3resok (XDR *, symlink3resok*); +extern  bool_t xdr_symlink3resfail (XDR *, symlink3resfail*); +extern  bool_t xdr_symlink3res (XDR *, symlink3res*); +extern  bool_t xdr_devicedata3 (XDR *, devicedata3*); +extern  bool_t xdr_mknoddata3 (XDR *, mknoddata3*); +extern  bool_t xdr_mknod3args (XDR *, mknod3args*); +extern  bool_t xdr_mknod3resok (XDR *, mknod3resok*); +extern  bool_t xdr_mknod3resfail (XDR *, mknod3resfail*); +extern  bool_t xdr_mknod3res (XDR *, mknod3res*); +extern  bool_t xdr_remove3args (XDR *, remove3args*); +extern  bool_t xdr_remove3resok (XDR *, remove3resok*); +extern  bool_t xdr_remove3resfail (XDR *, remove3resfail*); +extern  bool_t xdr_remove3res (XDR *, remove3res*); +extern  bool_t xdr_rmdir3args (XDR *, rmdir3args*); +extern  bool_t xdr_rmdir3resok (XDR *, rmdir3resok*); +extern  bool_t xdr_rmdir3resfail (XDR *, rmdir3resfail*); +extern  bool_t xdr_rmdir3res (XDR *, rmdir3res*); +extern  bool_t xdr_rename3args (XDR *, rename3args*); +extern  bool_t xdr_rename3resok (XDR *, rename3resok*); +extern  bool_t xdr_rename3resfail (XDR *, rename3resfail*); +extern  bool_t xdr_rename3res (XDR *, rename3res*); +extern  bool_t xdr_link3args (XDR *, link3args*); +extern  bool_t xdr_link3resok (XDR *, link3resok*); +extern  bool_t xdr_link3resfail (XDR *, link3resfail*); +extern  bool_t xdr_link3res (XDR *, link3res*); +extern  bool_t xdr_readdir3args (XDR *, readdir3args*); +extern  bool_t xdr_entry3 (XDR *, entry3*); +extern  bool_t xdr_dirlist3 (XDR *, dirlist3*); +extern  bool_t xdr_readdir3resok (XDR *, readdir3resok*); +extern  bool_t xdr_readdir3resfail (XDR *, readdir3resfail*); +extern  bool_t xdr_readdir3res (XDR *, readdir3res*); +extern  bool_t xdr_readdirp3args (XDR *, readdirp3args*); +extern  bool_t xdr_entryp3 (XDR *, entryp3*); +extern  bool_t xdr_dirlistp3 (XDR *, dirlistp3*); +extern  bool_t xdr_readdirp3resok (XDR *, readdirp3resok*); +extern  bool_t xdr_readdirp3resfail (XDR *, readdirp3resfail*); +extern  bool_t xdr_readdirp3res (XDR *, readdirp3res*); +extern  bool_t xdr_fsstat3args (XDR *, fsstat3args*); +extern  bool_t xdr_fsstat3resok (XDR *, fsstat3resok*); +extern  bool_t xdr_fsstat3resfail (XDR *, fsstat3resfail*); +extern  bool_t xdr_fsstat3res (XDR *, fsstat3res*); +extern  bool_t xdr_fsinfo3args (XDR *, fsinfo3args*); +extern  bool_t xdr_fsinfo3resok (XDR *, fsinfo3resok*); +extern  bool_t xdr_fsinfo3resfail (XDR *, fsinfo3resfail*); +extern  bool_t xdr_fsinfo3res (XDR *, fsinfo3res*); +extern  bool_t xdr_pathconf3args (XDR *, pathconf3args*); +extern  bool_t xdr_pathconf3resok (XDR *, pathconf3resok*); +extern  bool_t xdr_pathconf3resfail (XDR *, pathconf3resfail*); +extern  bool_t xdr_pathconf3res (XDR *, pathconf3res*); +extern  bool_t xdr_commit3args (XDR *, commit3args*); +extern  bool_t xdr_commit3resok (XDR *, commit3resok*); +extern  bool_t xdr_commit3resfail (XDR *, commit3resfail*); +extern  bool_t xdr_commit3res (XDR *, commit3res*); +extern  bool_t xdr_fhandle3 (XDR *, fhandle3*); +extern  bool_t xdr_dirpath (XDR *, dirpath*); +extern  bool_t xdr_name (XDR *, name*); +extern  bool_t xdr_mountstat3 (XDR *, mountstat3*); +extern  bool_t xdr_mountres3_ok (XDR *, mountres3_ok*); +extern  bool_t xdr_mountres3 (XDR *, mountres3*); +extern  bool_t xdr_mountlist (XDR *, mountlist*); +extern  bool_t xdr_mountbody (XDR *, mountbody*); +extern  bool_t xdr_groups (XDR *, groups*); +extern  bool_t xdr_groupnode (XDR *, groupnode*); +extern  bool_t xdr_exports (XDR *, exports*); +extern  bool_t xdr_exportnode (XDR *, exportnode*); + +extern void xdr_free_exports_list (struct exportnode *first); +extern void xdr_free_mountlist (mountlist ml); + +extern void xdr_free_write3args_nocopy (write3args *wa); +#endif  | 
